Ответ 1
Мне кажется, что мне нужно прояснить некоторые вещи об этом коде.
Первый, он предполагает, что обнаруженная область является идеальным квадратом, потому что она игнорирует некоторые из точек внутри squares[x]
для создания нового Mat
.
Второй, он также предполагает, что точки, которые делают область, были обнаружены по часовой стрелке, начиная с p0
в верхнем левом углу изображения:
(p0) 1st----2nd (p1)
| |
| |
(p3) 4th----3rd (p2)
что может быть неверно для всех обнаруженных регионов. Это означает, что этот код:
Rect roi(squares[x][0].x, squares[x][0].y,
squares[x][1].x - squares[x][0].x,
squares[x][3].y - squares[x][0].y);
вероятно, создаст ROI с недопустимыми размерами, такими как отрицательные значения ширины и высоты, и почему OpenCV бросает на вас cv::Exception
на Mat subimage(image, roi);
.
Что вы должны сделать, это написать код, который будет идентифицировать верхнюю левую точку региона и называть его p0
, затем ближайший neightbor с правой стороны, p1
, затем найдите нижнюю правую точку области и назовите ее p2
, а затем что осталось p3
. После этого сборка ROI проста:
Rect roi(p0.x, p0.y,
p1.x - p0.x,
p3.y - p0.y);
ИЗМЕНИТЬ
Я нашел отличное решение при чтении документации v2.3 OpenCV. Он автоматизирует процесс, который я описал ранее, и делает вещи намного проще и чисты. Вы можете использовать этот трюк, чтобы заказать 4 точки в векторе для значимой структуры Rect
:
// Data returned and filled by findSquares(). Check the example squares.cpp for more info on this function.
vector<vector<Point> > squares;
for (size_t i = 0; i < squares.size(); i++)
{
Rect rectangle = boundingRect(Mat(squares[i]));
cout << "#" << i << " rectangle x:" << rectangle.x << " y:" << rectangle.y << " " << rectangle.width << "x" << rectangle.height << endl;
}