2025年标准椭圆方程推导

标准椭圆方程推导初衷 用 opencv 拟合椭圆后 想评估一下拟合的质量 即被拟合点与拟合结果的接近程度 我首先想到的办法是将被拟合点带入椭圆方程 f x y A x

大家好,我是讯享网,很高兴认识大家。

初衷

用opencv拟合椭圆后,想评估一下拟合的质量,即被拟合点与拟合结果的接近程度。我首先想到的办法是将被拟合点带入椭圆方程 f ( x , y ) = A x 2 + B x y + C y 2 + D x + E y + F f(x, y) =Ax^2+Bxy+Cy^2+Dx+Ey+F f(x,y)=Ax2+Bxy+Cy2+Dx+Ey+F,如果一个点正好在椭圆上,那么 f ( x , y ) = 0 f(x, y) =0 f(x,y)=0,而一个点偏离椭圆越多,则其计算值越大,因此可以用来评估被被拟合点的偏差。 opencv 中 fitEllipse() 函数计算得到的是椭圆的中心坐标、长短轴的长度和长轴与 + x +x +x 轴的夹角(需要注意的是,拟合结果的 height 才是长轴),需要根据这些信息推导椭圆的标准方程。


推导

中心在原点且长轴在x轴上的椭圆方程为:
x 2 a 2 + y 2 b 2 = 1 (1) \dfrac{x^2}{a^2} + \dfrac{y^2}{b^2} = 1 \tag 1 a2x2+b2y2=1(1)其中, a a a b b b分别是长半轴和短半轴。若椭圆长轴与正x轴夹角为 θ \theta θ(逆时针),且中心坐标为 ( x 0 , y 0 ) (x_0,y_0) (x0,y0)。其任意一点平移 ( − x 0 , − y 0 ) (-x_0,-y_0) (x0,y0)再旋转 − θ -\theta θ即满足标准椭圆方程。

首先考虑点 ( x , y ) (x,y) (x,y)绕原点顺时针旋转角度 θ \theta θ ( x ′ , y ′ ) (x',y') (x,y)
用参数方程表示点 ( x , y ) (x,y) (x,y)和点 ( x ′ , y ′ ) (x',y') (x,y)
{ x = t cos ⁡ ϕ y = t sin ⁡ ϕ (2) \begin{cases} x = t\cos\phi\\ y = t\sin\phi \end{cases} \tag 2 { x=tcosϕy=tsinϕ(2) { x ′ = t cos ⁡ ( ϕ − θ ) = t ( cos ⁡ ϕ cos ⁡ θ + sin ⁡ ϕ sin ⁡ θ ) y ′ = t sin ⁡ ( ϕ − θ ) = t ( sin ⁡ ϕ cos ⁡ θ − cos ⁡ ϕ sin ⁡ θ ) (3) \begin{cases} x' = t\cos(\phi-\theta)=t(\cos\phi\cos\theta+\sin\phi\sin\theta)\\ y' = t\sin(\phi-\theta)=t(\sin\phi\cos\theta-\cos\phi\sin\theta) \end{cases} \tag 3 { x=tcos(ϕθ)=t(cosϕcosθ+sinϕsinθ)y=tsin(ϕθ)=t(sinϕcosθcosϕsinθ)(3)因此:
{ x ′ = x cos ⁡ θ + y sin ⁡ θ y ′ = − x sin ⁡ θ + y cos ⁡ θ (4) \begin{cases} x' = x\cos\theta+y\sin\theta\\ y' = -x\sin\theta+y\cos\theta \end{cases} \tag 4 { x=xcosθ+ysinθy=xsinθ+ycosθ(4)继而可得一般椭圆方程为:
[ ( x − x 0 ) cos ⁡ θ + ( y − y 0 ) sin ⁡ θ ] 2 a 2 + [ ( x − x 0 ) sin ⁡ θ − ( y − y 0 ) cos ⁡ θ ] 2 b 2 = 1 \dfrac{\left[(x-x_0)\cos\theta+(y-y_0)\sin\theta\right]^2}{a^2}+ \dfrac{\left[(x-x_0)\sin\theta-(y-y_0)\cos\theta\right]^2}{b^2}=1 a2[(xx0)cosθ+(yy0)sinθ]2+b2[(xx0)sinθ(yy0)cosθ]2=1化简为 A x 2 + B x y + C y 2 + D x + E y + F = 0 Ax^2+Bxy+Cy^2+Dx+Ey+F=0 Ax2+Bxy+Cy2+Dx+Ey+F=0 的形式可得:
A = cos ⁡ 2 θ a 2 + sin ⁡ 2 θ b 2 B = 2 sin ⁡ θ cos ⁡ θ ( 1 a 2 − 1 b 2 ) C = sin ⁡ 2 θ a 2 + cos ⁡ 2 θ b 2 D = − 2 [ cos ⁡ θ ( x 0 cos ⁡ θ + y 0 sin ⁡ θ ) a 2 + sin ⁡ θ ( x 0 sin ⁡ θ − y 0 cos ⁡ θ ) b 2 ] E = − 2 [ sin ⁡ θ ( x 0 cos ⁡ θ + y 0 sin ⁡ θ ) a 2 − cos ⁡ θ ( x 0 sin ⁡ θ − y 0 cos ⁡ θ ) b 2 ] F = ( x 0 cos ⁡ θ + y 0 sin ⁡ θ ) 2 a 2 + ( x 0 sin ⁡ θ − y 0 cos ⁡ θ ) 2 b 2 − 1 (5) \begin{aligned} A=&\dfrac{\cos^2\theta}{a^2}+\dfrac{\sin^2\theta}{b^2} \\ B=&2\sin\theta\cos\theta\left(\frac{1}{a^2}-\frac{1}{b^2}\right) \\ C=&\dfrac{\sin^2\theta}{a^2}+\dfrac{\cos^2\theta}{b^2} \\ D=&-2\left[\dfrac{\cos\theta(x_0\cos\theta+y_0\sin\theta)}{a^2}+ \dfrac{\sin\theta(x_0\sin\theta-y_0\cos\theta)}{b^2}\right] \\ E=&-2\left[\dfrac{\sin\theta(x_0\cos\theta+y_0\sin\theta)}{a^2}- \dfrac{\cos\theta(x_0\sin\theta-y_0\cos\theta)}{b^2}\right] \\ F=&\dfrac{(x_0\cos\theta+y_0\sin\theta)^2}{a^2}+ \dfrac{(x_0\sin\theta-y_0\cos\theta)^2}{b^2}-1 \end{aligned} \tag 5 A=B=C=D=E=F=a2cos2θ+b2sin2θ2sinθcosθ(a21b21)a2sin2θ+b2cos2θ2[a2cosθ(x0cosθ+y0sinθ)+b2sinθ(x0sinθy0cosθ)]2[a2sinθ(x0cosθ+y0sinθ)b2cosθ(x0sinθy0cosθ)]a2(x0cosθ+y0sinθ)2+b2(x0sinθy0cosθ)21(5)


代码

在 C++ 中实现上述计算的函数为:


讯享网

cv::Mat normEllipseParams(cv::RotatedRect box) { 
    double params[6]; cv::Mat rst(6, 1, CV_64FC1, params); double theta = box.angle / 180 * CV_PI; double st = sin(theta); double ct = cos(theta); double a = box.size.width / 2; double b = box.size.height / 2; double a2 = a * a; double b2 = b * b; double x0 = box.center.x; double y0 = box.center.y; double xcys = x0 * ct + y0 * st; double xsyc = x0 * st - y0 * ct; params[0] = ct * ct / a2 + st * st / b2; params[1] = 2 * st * ct * (1 / a2 - 1 / b2); params[2] = st * st / a2 + ct * ct / b2; params[3] = -2 * (ct * xcys / a2 + st * xsyc / b2); params[4] = -2 * (st * xcys / a2 - ct * xsyc / b2); params[5] = xcys * xcys / a2 + xsyc * xsyc / b2 - 1; return rst.clone(); } 

讯享网

返回的 Mat 即 A~F 六个参数。


后记

测试后发现一个问题,计算椭圆方程的方法计算比较复杂,而且计算结果受椭圆大小的影响,难以直观地反应点的偏差值。后来我发现其实可以利用“椭圆上的点到其两个焦点的距离之和不变”这一性质来判断一个点偏离椭圆的程度。

  1. 椭圆的两个焦点在其长轴上,且与中心的距离为 a 2 − b 2 \sqrt{a^2-b^2} a2b2 ;
  2. 椭圆上的点到两个焦点的距离之和为 2 a 2a 2a.

计算椭圆焦点的函数为:

讯享网std::array<cv::Point2f, 2> calcFocal(cv::RotatedRect& ellipse) { 
    if (ellipse.size.width < ellipse.size.height) { 
    swap(ellipse.size.width, ellipse.size.height); ellipse.angle -= 90; } float a = ellipse.size.width / 2; float b = ellipse.size.height / 2; float c = sqrt(a * a - b * b); float theta = ellipse.angle / 180 * CV_PI; cv::Point2f delta(c * cos(theta), c * sin(theta)); return { 
   ellipse.center + delta, ellipse.center - delta}; } 

对于任意一个被拟合的点,只要计算其到两焦点的距离之和与 2 a 2a 2a 的差值,即可知道它与椭圆的像素偏差大小。

小讯
上一篇 2025-01-06 09:23
下一篇 2025-01-09 19:31

相关推荐

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/69138.html