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


i want extract red ball 1 picture , detected ellipse matrix in picture.

here example: enter image description here

i threshold picture, find contour of red ball using findcontour() function , use fitellipse() fit ellipse.

but want coefficient of ellipse. because fitellipse() return rotation rectangle (rotatedrect), need re-write function.

one ellipse can expressed ax^2 + by^2 + cxy + dx + ey + f = 0; want u=(a,b,c,d,e,f) or u=(a,b,c,d,e) if f 1 (to construct ellipse matrix).

i read source code of fitellipse(), there totally 3 svd process, think can above coefficients results of 3 svd process. quite confused each result (variable cv::mat x) of each svd process represent , why there 3 svd here?

here 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 < 5 )         cv_error( cv_stsbadsize, "there should @ least 5 points fit ellipse" );      // new fitellipse algorithm, contributed dr. daniel weiss     point2f c(0,0);     double gfp[5], rp[5], t;     const double min_eps = 1e-8;     bool is_float = depth == cv_32f;     const point* ptsi = points.ptr<point>();     const point2f* ptsf = points.ptr<point2f>();      autobuffer<double> _ad(n*5), _bd(n);     double *ad = _ad, *bd = _bd;      // first fit parameters - e     mat a( n, 5, cv_64f, ad );     mat b( n, 1, cv_64f, bd );     mat x( 5, 1, cv_64f, gfp );      for( = 0; < n; i++ )     {         point2f p = is_float ? ptsf[i] : point2f((float)ptsi[i].x, (float)ptsi[i].y);         c += p;     }     c.x /= n;     c.y /= n;      for( = 0; < n; i++ )     {         point2f p = is_float ? ptsf[i] : point2f((float)ptsi[i].x, (float)ptsi[i].y);         p -= c;          bd[i] = 10000.0; // 1.0?         ad[i*5] = -(double)p.x * p.x; // - c signs inverted proposed app         ad[i*5 + 1] = -(double)p.y * p.y;         ad[i*5 + 2] = -(double)p.x * p.y;         ad[i*5 + 3] = p.x;         ad[i*5 + 4] = p.y;     }      solve(a, b, x, decomp_svd);      // use general-form parameters - e find ellipse center:     // differentiate general form wrt x/y 2 equations cx , cy     = mat( 2, 2, cv_64f, ad );     b = mat( 2, 1, cv_64f, bd );     x = mat( 2, 1, cv_64f, rp );     ad[0] = 2 * gfp[0];     ad[1] = ad[2] = gfp[2];     ad[3] = 2 * gfp[1];     bd[0] = gfp[3];     bd[1] = gfp[4];     solve( a, b, x, decomp_svd );      // re-fit parameters - c center coordinates     = mat( n, 3, cv_64f, ad );     b = mat( n, 1, cv_64f, bd );     x = mat( 3, 1, cv_64f, gfp );     for( = 0; < n; i++ )     {         point2f p = is_float ? ptsf[i] : point2f((float)ptsi[i].x, (float)ptsi[i].y);         p -= c;         bd[i] = 1.0;         ad[i * 3] = (p.x - rp[0]) * (p.x - rp[0]);         ad[i * 3 + 1] = (p.y - rp[1]) * (p.y - rp[1]);         ad[i * 3 + 2] = (p.x - rp[0]) * (p.y - rp[1]);     }     solve(a, b, x, decomp_svd);      // store angle , radii     rp[4] = -0.5 * atan2(gfp[2], gfp[1] - gfp[0]); // convert app angle usage     if( fabs(gfp[2]) > min_eps )         t = gfp[2]/sin(-2.0 * rp[4]);     else // ellipse rotated 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 < -180 )         box.angle += 360;     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

the function fitellipse returns rotatedrect contains parameters of ellipse.

an ellipse defined 5 parameters:

  • xc : x coordinate of center
  • yc : y coordinate of 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     = e.size.width  / 2;    // width >= height float b     = e.size.height / 2; float theta = e.angle;              // in degrees 

you can draw ellipse function ellipse using rotatedrect:

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

or, equivalently using ellipse parameters:

ellipse(res, point(xc, yc), size(a, b), theta, 0.0, 360.0, scalar(0,255,0)); 

if need values of coefficients of implicit equation, can (from wikipedia):

enter image description here

so, can parameters need rotatedrect, , don't need change function fitellipse. solve function used solve linear systems or least-squares problems. using svd decomposition method system can over-defined and/or matrix src1 can singular.

for more details on algorithm, can see paper of fitzgibbon proposed fit ellipse method.


Comments