how to check if a contour is an ellipse?

2019-08-07 10:01发布

问题:

I am trying to detect ellipse in an image using opencv. I find the contours which include ellipse and also some other ones.

Any suggestions that how can I check which contours are ellipse?

回答1:

if I understand you correctly, you have detected contours some of them are ellipses and some are not and you want to be able to decide which ones are. Is it right? If yes, I would suggest to use cv::fitEllipse(). The doc says that it fits an ellipse to a vector of points so that R-squared is minimal. Unfortunately, the function does not return explicitly the R-squared value. You can maybe implement it yourself...

As a workaround, you can also use a something such as:

  1. Get the contour C
  2. Fit an ellipse E to C
  3. Compare E to C.

To compare them you can use moments (cf. cv::moments() and cv::matchShapes()). I do not think you need invariant moments here, though.

Alternatively, you can draw C and E find what proportion of there surface overlap.

Good luck,



回答2:

fitEllipse give us RotatedRect.

And we can use ellipse specific property that can be transformed in to circle.

double is_ellipse( std::vector<cv::Point>  const& cloud, RotatedRect const& rr )
{
    double distance =0;

    for( auto const& point: cloud )
    {
        Point2f unit;
        unit.x = ( ( rr.center.x - point.x  ) * cos( - rr.angle*(3.1415926/180) ) -  ( rr.center.y - point.y  ) * sin( - rr.angle*(3.1415926/180) ) ) * 2 / rr.size.width ;
        unit.y = ( ( rr.center.x - point.x  ) * sin( - rr.angle*(3.1415926/180) ) +  ( rr.center.y - point.y  ) * cos( - rr.angle*(3.1415926/180) ) ) * 2 / rr.size.height;

        double len = sqrt( unit.x* unit.x +  unit.y * unit.y );
        distance += fabs( 1- len );
    }
    return distance / cloud.size();
}

Here is used to calculate average distance from border of circle. It is easy to modify some other statistic functions like: max, deviation.



回答3:

@Ahsan - you have to iterate through all the contours and try to fit the ellipse. If you find the curve fitting math difficult a short route will be

like - iterate through each contour - discard non convex contours - now make a mask of the current contour and do shapeMatching using the cv::matchShapes function.