I am working on a shape recognition app. At this moment a set of points (x,y) is determined by corner detector (red points, img. 2.). Four of these points (in red frames, img. 2.) are vertices of a rectangle (sometimes a little deformed rectangle). What would be the best way to find them among others?
Here is an example of an input image:
And it looks like this after corner detection:
Now we know that opposite sides in a rectangle are equal, and the diagonals of a rectangle are also equal. That means we have threee pairs of euql distances. Say for ABCD, AB = CD, BC = DA and AC = BD. So we can safely assume ABCD is a rectangle if AB^BC^CD^AD^BD^AC ==0.
Approach: The idea is to pick any point and calculate its distance from the rest of the points. Let the picked point be 'p'. To form a square, the distance of two points must be the same from 'p', let this distance be d. The distance from one point must be different from that d and must be equal to √2 times d.
A rectangle is a quadrilateral with four right angles. Thus, all the angles in a rectangle are equal (360°/4 = 90°). Moreover, the opposite sides of a rectangle are parallel and equal, and diagonals bisect each other.
This is not an answer to your question - it's just suggestion.
In my opinion corner detector is a bad way to detect rectangles - it will take much time to calculate all point distances as mathematician1975 suggested. You have to use another technique in this situation:
Update:
Here's another solution that should also work in gray images.
ContourArea / BoundingReactangleArea > constant
I take this constant
as 0.9.
And this algorithm gave me next result:
Here's OpenCV code:
Mat src = imread("input.jpg"), gray, result;
vector<vector<Point> > contours;
vector<Vec4i> hierarchy;
result = Mat(src.size(), CV_8UC1);
cvtColor(src, src, CV_BGR2GRAY);
threshold(src, gray, 200, 255, THRESH_BINARY_INV);
findContours(gray, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0, 0));
result = Scalar::all(0);
for (size_t i=0; i<contours.size(); i++)
{
Rect rect = boundingRect(contours[i]);
if (rect.area() > 1000)
{
double area = contourArea(contours[i]);
if (area/rect.area() > 0.9)
{
drawContours(result, contours, i, Scalar(255), -1);
}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With