I feel like I need to clarify a few things about that code.
First, it assumes that the region detected is a perfect square because it ignores some of the points inside squares[x]
to create a new Mat
.
Second, it also assumes that the points that make the region were detected in the clockwise direction, starting with p0
in the top-left corner of the image:
(p0) 1st----2nd (p1)
| |
| |
(p3) 4th----3rd (p2)
which might not be true for all the regions detected. That means that this code:
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);
probably will generate a ROI with invalid dimensions, such as negative width and height values, and that's why OpenCV throws a cv::Exception
at you on Mat subimage(image, roi);
.
What you should do, is write a code that will identify the top-left point of the region and call it p0
, then it's nearest neightbor on the right side, p1
, then find the bottom-right point of the region and call it p2
, and then what's left is p3
. After this, assembling the ROI is easy:
Rect roi(p0.x, p0.y,
p1.x - p0.x,
p3.y - p0.y);
EDIT:
I found an excellent solution while reading the documentation of the v2.3 of OpenCV. It automates the process I described earlier and it make things so much easier and clean. You can use this trick to order the 4 Points in the vector to a meaningful Rect
structure:
// 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;
}
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…