How can I get ellipse coefficient from fitEllipse function of OpenCV?

匿名 (未验证) 提交于 2019-12-03 01:23:02

问题:

I want to extract the red ball from one picture and get the detected ellipse matrix in picture.

Here is my example:

I threshold the picture, find the contour of red ball by using findContour() function and use fitEllipse() to fit an ellipse.

But what I want is to get coefficient of this ellipse. Because the fitEllipse() return a rotation rectangle (RotatedRect), so I need to re-write this function.

One Ellipse can be expressed as Ax^2 + By^2 + Cxy + Dx + Ey + F = 0; So I want to get u=(A,B,C,D,E,F) or u=(A,B,C,D,E) if F is 1 (to construct an ellipse matrix).

I read the source code of fitEllipse(), there are totally three SVD process, I think I can get the above coefficients from the results of those three SVD process. But I am quite confused what does each result (variable cv::Mat x) of each SVD process represent and why there are three SVD here?

Here is this function:

cv::RotatedRect cv::fitEllipse( InputArray _points ) {    Mat points = _points.getMat();    int i, n = points.checkVector(2);    int depth = points.depth();    CV_Assert( n >= 0 && (depth == CV_32F || depth == CV_32S));     RotatedRect box;     if( n ();     const Point2f* ptsf = points.ptr();      AutoBuffer _Ad(n*5), _bd(n);     double *Ad = _Ad, *bd = _bd;      // first fit for parameters A - E     Mat A( n, 5, CV_64F, Ad );     Mat b( n, 1, CV_64F, bd );     Mat x( 5, 1, CV_64F, gfp );      for( i = 0; i  min_eps )         t = gfp[2]/sin(-2.0 * rp[4]);     else // ellipse is rotated by an integer multiple of pi/2         t = gfp[1] - gfp[0];     rp[2] = fabs(gfp[0] + gfp[1] - t);     if( rp[2] > min_eps )         rp[2] = std::sqrt(2.0 / rp[2]);     rp[3] = fabs(gfp[0] + gfp[1] + t);     if( rp[3] > min_eps )         rp[3] = std::sqrt(2.0 / rp[3]);      box.center.x = (float)rp[0] + c.x;     box.center.y = (float)rp[1] + c.y;     box.size.width = (float)(rp[2]*2);     box.size.height = (float)(rp[3]*2);     if( box.size.width > box.size.height )     {         float tmp;         CV_SWAP( box.size.width, box.size.height, tmp );         box.angle = (float)(90 + rp[4]*180/CV_PI);     }     if( box.angle  360 )         box.angle -= 360;      return box; } 

The source code link: https://github.com/Itseez/opencv/blob/master/modules/imgproc/src/shapedescr.cpp

回答1:

The function fitEllipse returns a RotatedRect that contains all the parameters of the ellipse.

An ellipse is defined by 5 parameters:

  • xc : x coordinate of the center
  • yc : y coordinate of the center
  • a : major semi-axis
  • b : minor semi-axis
  • theta : rotation angle

You can obtain these parameters like:

RotatedRect e = fitEllipse(points);  float xc    = e.center.x; float yc    = e.center.y; float a     = e.size.width  / 2;    // width >= height float b     = e.size.height / 2; float theta = e.angle;              // in degrees 

You can draw an ellipse with the function ellipse using the RotatedRect:

ellipse(image, e, Scalar(0,255,0));  

or, equivalently using the ellipse parameters:

ellipse(res, Point(xc, yc), Size(a, b), theta, 0.0, 360.0, Scalar(0,255,0)); 

If you need the values of the coefficients of the implicit equation, you can do like (from Wikipedia):

So, you can get the parameters you need from the RotatedRect, and you don't need to change the function fitEllipse. The solve function is used to solve linear systems or least-squares problems. Using the SVD decomposition method the system can be over-defined and/or the matrix src1 can be singular.

For more details on the algorithm, you can see the paper of Fitzgibbon that proposed this fit ellipse method.



标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!