Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to find the best quadrilateral to approximate an OpenCV contour?

I have an OpenCV contour c which is close to a quadrilateral in its shape, but it can have 4 to multiple of dozens of points.

I want to find the quadrilateral q which is the closest to the contour c (one way could be to minimize the area of the difference between them).

I currently use

q = cv2.approxPolyDP(c, 0.02 * cv2.arcLength(c, True), closed=True)

but the result is not always a quadrilateral. I have already tried techniques like those in cv2.approxPolyDP() , cv2.arcLength() How these works and in How to force approxPolyDP() to return only the best 4 corners? - Opencv 2.4.2 (binary search for example), but it doesn't always yield a quadrilateral.

Is there another way (probably with something else than approxPolyDP?) to find the best quadrilateral approximation to a contour?

Note: another linked question is Crop image based on largest quadrilateral contour OpenCV but it does not give a solution to this problem.

like image 512
Basj Avatar asked Sep 18 '25 02:09

Basj


1 Answers

I recently had a similar problem, but instead of approximating a contour with a general quadrilateral, I tried to approximate it with a rectangle. I hope that my solution would be helpful to your problem as well.

I used the cv.minAreaRect method. This method finds the enclosing Rotated Rectangle of a set of points with minimal area. In python opencv, a Rotated Rectangle is built out of (center_x, center_y), (width, height), angle_in_degrees. I suggest you to check this link to avoid confusion about the returned angle_in_degrees value, and for more useful information regarding "minAreaRect" method.

Here is a simple usage example of the "minAreaRect" method:

import cv2

def check_rectangle_approx(contour):
    rectangle = cv2.minAreaRect(contour)
    (center_x, center_y), (width, height), angle = rectangle

    return width * height - cv2.contourArea(contour) < SOME_THERSHOLD_VLAUE

In my case, where I had close to rectangle contours, minAreaRect() returned decent approximations. Hope it will be the same for you.

like image 121
Y_Z Avatar answered Sep 19 '25 18:09

Y_Z