Ask Your Question

Fit ellipse with most points on contour (instead of least squares)

asked 2019-04-29 11:52:55 -0500

Jordan gravatar image

updated 2019-04-29 15:24:27 -0500

I have a binarized image, which I've already used open/close morphology operations on (this is as clean as I can get it, trust me on this) that looks like so: image description

As you can see, there is an obvious ellipse with some distortion on the top. I'm trying to figure out how to fit an ellipse to it, such that it maximizes the number of points on the fitted ellipse that correspond to edges on the shape. That is, I want a result like this: image description

However, I can't seem to find a way in OpenCV to do this. Using the common tools of fitEllipse (blue line) and minAreaRect (green line), I get these results: image description

Which obviously do not represent the actual ellipse I'm trying to detect. Any thoughts as to how I could accomplish this? Happy to see examples in Python or C++.

EDIT: Original image and intermediate processing steps below, as requested: Original image: image description After an Otsu threshold: image description After Opening morph (7x7 kernel): image description

And then the image at the very top of this post is after a Closing morph (7x7 kernel). Obviously, this particular image could be improved by manually setting a threshold level. However, the images I have to process could be substantially different in lighting conditions, which is why I must use something adaptive (like Otsu).

edit retag flag offensive close merge delete


Try repeatedly calling the function after rejecting outliers? What you want is iteratively reweighted least-squares. cv::fitLine() does this, so take a look at that source for inspiration.

Der Luftmensch gravatar imageDer Luftmensch ( 2019-04-29 13:04:12 -0500 )edit

OK, interesting. How would I determine which points on a contour are outliers, after fitting an ellipse?

Jordan gravatar imageJordan ( 2019-04-29 13:20:58 -0500 )edit

@Jordan . Can you post original image?

supra56 gravatar imagesupra56 ( 2019-04-29 13:28:12 -0500 )edit

@supra56 Sure, I edited the post with more images.

Jordan gravatar imageJordan ( 2019-04-29 15:24:48 -0500 )edit

1 answer

Sort by » oldest newest most voted

answered 2019-04-29 14:56:46 -0500

kbarni gravatar image

If the object is a circle (not ellipse), try the circular Hough transform on the contours of the object.

Otherwise you can implement a RANSAC detector. It's not part of OpenCV, but it's fairly simple: select a few random points on the contour, fit an ellipse*, then count the number of contour points that are on the ellipse. Then repeat this many times, and select the solution that has the most contour points on the ellipse.

*To fit an ellipse on random points, select 6 points on the contour and solve the equation:


for each (x,y). Then, when you have determined the 6 parameters (a,b,c,d,e,f), take every contour point and see if it verifies the equation above.

edit flag offensive delete link more


Thanks for the ideas. Could you post a sample of running the circular Hough transform on a contour? My impression was that the HoughCircles function does a Canny detection and other steps first, which seems unnecessary/wasteful when contours have already been detected.

Also, could I not just use the fitEllipse function on the 6 random points, instead of manually solving for that equation?

Jordan gravatar imageJordan ( 2019-04-29 15:16:29 -0500 )edit

Could you post a sample of running the circular Hough transform on a contour?

see here

i changed the code as below to find the circle in your image

img = cv.medianBlur(img, 25)
cimg = src.copy() # numpy function

circles = cv.HoughCircles(img, cv.HOUGH_GRADIENT, 1, 500, np.array([]), 100, 50, 0, 0)
sturkmen gravatar imagesturkmen ( 2019-04-29 19:52:07 -0500 )edit

@sturkmen in your sample code, is "img" the original image, or the thresholded/opened/closed one? I don't think Hough will work for me though, since I need to fit an ellipse, not a circle. In my application, there could be as much as a 2% difference between the major and minor axes, and I need to be able to detect that difference.

Jordan gravatar imageJordan ( 2019-04-29 21:42:49 -0500 )edit

Well, 2% difference isn't that much, it might be difficult to detect (1 pixel on a 50 pixel radius circle) essentially if there is noise.

Anyway, you can check the RANSAC algorithm I described in my answer.

kbarni gravatar imagekbarni ( 2019-04-30 02:04:18 -0500 )edit

Question Tools

1 follower


Asked: 2019-04-29 11:52:55 -0500

Seen: 3,457 times

Last updated: Apr 29 '19