最小二乘法拟合圆公式推导及vc实现

 最小二乘法(least squares analysis)是一种 数学 优化 技术,它通过 最小化 误差 的平方和找到一组数据的最佳 函数 匹配。 最小二乘法是用最简的方法求得一些绝对不可知的真值,而令误差平方之和为最小。 最小二乘法通常用于 曲线拟合 (least squares fitting) 。这里有 拟合圆曲线 的公式推导过程 和 vc实现。








VC实现的代码:
void  CViewActionImageTool::LeastSquaresFitting()
{
    
if (m_nNum<3)
    
{
        
return;
    }


    
int i=0;

    
double X1=0;
    
double Y1=0;
    
double X2=0;
    
double Y2=0;
    
double X3=0;
    
double Y3=0;
    
double X1Y1=0;
    
double X1Y2=0;
    
double X2Y1=0;

    
for (i=0;i<m_nNum;i++)
    
{
        X1 
= X1 + m_points[i].x;
        Y1 
= Y1 + m_points[i].y;
        X2 
= X2 + m_points[i].x*m_points[i].x;
        Y2 
= Y2 + m_points[i].y*m_points[i].y;
        X3 
= X3 + m_points[i].x*m_points[i].x*m_points[i].x;
        Y3 
= Y3 + m_points[i].y*m_points[i].y*m_points[i].y;
        X1Y1 
= X1Y1 + m_points[i].x*m_points[i].y;
        X1Y2 
= X1Y2 + m_points[i].x*m_points[i].y*m_points[i].y;
        X2Y1 
= X2Y1 + m_points[i].x*m_points[i].x*m_points[i].y;
    }


    
double C,D,E,G,H,N;
    
double a,b,c;
    N 
= m_nNum;
    C 
= N*X2 - X1*X1;
    D 
= N*X1Y1 - X1*Y1;
    E 
= N*X3 + N*X1Y2 - (X2+Y2)*X1;
    G 
= N*Y2 - Y1*Y1;
    H 
= N*X2Y1 + N*Y3 - (X2+Y2)*Y1;
    a 
= (H*D-E*G)/(C*G-D*D);
    b 
= (H*C-E*D)/(D*D-G*C);
    c 
= -(a*X1 + b*Y1 + X2 + Y2)/N;

    
double A,B,R;
    A 
= a/(-2);
    B 
= b/(-2);
    R 
= sqrt(a*a+b*b-4*c)/2;

    m_fCenterX 
= A;
    m_fCenterY 
= B;
    m_fRadius 
= R;

    
return;
}


工程下载

编译运行后随便打开一个图片,当然最好是全白的图片,然后就点吧,大于三个点后就会开始拟合。红线画的圆为拟合的圆,深蓝的点为鼠标点击设置的样本点。单击鼠标右键清空样本集。

转自:http://www.cnblogs.com/dotLive/archive/2007/04/06/524633.html


看了下面的评论很有启发:贴上来,可以仔细研读下

#2楼   2007-04-05 09:53 |  路不平[未注册用户]
公式错误! 

最小二乘法的意义是距离差值的平方(di-R)^2,不是距离平方差的平方(di^2-R^2)^2 

两者是不同的!事实上 

(di^2-R^2)=(di-R)(di+R) 

因此,以上结果将使圆半径“趋小”! 
  
#3楼 [ 楼主2007-04-05 13:37 |  .Live   
@路不平 
其实是一样的。 

最小化 误差 的平方和,将距离平方差认为是 误差,可以表征和真实值得误差大小,使之最小也可以得到一个相对较优的拟合值。同时简化公式的推导。 

如果使用距离的平方差,则平方和中会出现开根号,公式就很难推导了。
  
#4楼   2007-04-06 09:18 |  路不平[未注册用户]
回:dotLive 

我编制过关于圆最小二乘的程序。起先我以为两者是一样的,就是:评价(di-R)^2与评价(di^2-R^2)^2是一样的。 
但正如你所说,后者是把R^2作为真值进行考虑的。当然如果散点恰能构成一个圆,两者是一样的。因为: 
(a^2-b^2)=(a+b)(a-b)=0 
但我实际编程后(采用最速下降法)发现,后者的半径偏小(散点越不接近于圆越明显)!为什么呢?因为,最小二乘的几何原理考察的是“距离”的误差(di-R)。那么变成平方差 (di^2-R^2)后,事实上是给(di-R)乘上了一个(di+R约=2R)的权重,最终实际的结果,当然是半径偏小。 
事实上,你可以通过编程发现两者的差异! 
当然上述推导依然是有价值的,因为这个结果作为迭代法的初值是再合适不过了! 
实际的推导是不“可解”的,否则,《数学手册》就会出现相应的方法,就象线性回归和抛物线回归一样! 


  
#5楼 [ 楼主2007-04-06 10:30 |  .Live   
@路不平 
你的分析是对的,对我很有启发。我没有考虑到偏差的程度是如何变化的。你的分析应该说验证了这个推导在整体圆检测算法中的可行性。 
事实上这个拟合公式确实迭代检测圆的一个步骤,我采取的方法是每次迭代删除方差大于某个阈值的点,认为它们是非圆上的点。 
要使用这个迭代拟合的方法,还需要前面粗检测来限定范围,以保证进行拟合的点在圆周的一个特定范围内;最后删除点的迭代次数,也就是迭代停止条件也需要考虑和分析。最后我们希望是可以得到全部都是圆上的点,或者都是离真实边缘很接近的点,那么拟合的圆稍微有所偏差也是可以接受的。 
还有一点是,这个检测的算法是假设在很高的分辨率下进行的,因此需要采用一些牺牲少量精度,大量降低计算量的方法,检测精度已经由高分辨的采集装置保证了一部分。


  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值