i want extract red ball 1 picture , detected ellipse matrix in picture.
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):
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
Post a Comment