Image processing 最佳圆拟合算法

Image processing 最佳圆拟合算法,image-processing,geometry,computer-vision,Image Processing,Geometry,Computer Vision,我需要一个非常精确的算法来将圆拟合到数据点集(实际上我需要确定圆心)。数据是在对图像进行二值化和分割之后产生的。 我尝试了简单的质心和加权质心算法,还预先制作了OpenCv::fitEllipse函数。我已经从OpenCV函数中获得了最好的结果,但仍然不够精确。当中心定位在亚像素区域时,结果会显著受损。 即使在处理建模数据时,我获得的精度也不够,这是很糟糕的,因为最终,程序将不得不处理comeras捕获的数据。 你有什么建议我应该寻找什么样的算法,或者你有什么现成的解决方案吗?我宁愿避免链接任何

我需要一个非常精确的算法来将圆拟合到数据点集(实际上我需要确定圆心)。数据是在对图像进行二值化和分割之后产生的。 我尝试了简单的质心和加权质心算法,还预先制作了OpenCv::fitEllipse函数。我已经从OpenCV函数中获得了最好的结果,但仍然不够精确。当中心定位在亚像素区域时,结果会显著受损。 即使在处理建模数据时,我获得的精度也不够,这是很糟糕的,因为最终,程序将不得不处理comeras捕获的数据。 你有什么建议我应该寻找什么样的算法,或者你有什么现成的解决方案吗?我宁愿避免链接任何外部LIB。 谢谢你的帮助。

编辑: 校准目标可以定位在视野的任何区域。以下是我通过OpenCV程序获得的最佳结果:

169,367 748,345  
167,557 820,788  
165,690 893,158  
164,047 965,197  
162,715 1036,729  
161,575 1108,089  
160,477 1179,552  
233,297 1015,313  
232,076 1086,965  
220,359 1229,578  
268,494 1160,275  
339,544 1162,980  
362,017 1235,669  
433,390 1238,491  
482,754 1168,299  
505,233 1241,039  
554,856 1170,664  
577,302 1243,439  
627,331 1172,795  
649,507 1245,665  
713,572 588,896  
711,995 661,853  
710,440 735,034  
708,722 808,856  
707,018 882,674  
705,377 956,169  
703,609 1029,211  
701,716 1101,950  
699,760 1174,689  
721,895 1247,620  
785,829 614,754  
784,344 687,750  
782,819 761,315  
781,292 835,225  
779,389 908,975  
777,619 982,335  
775,688 1055,275  
773,672 1128,091  
771,603 1200,724  
编辑:数值生成的模型和中心的实际坐标:

“最佳”取决于输入数据中的噪声类型。如果源数据点中没有噪声,则问题很简单:只需选取3个点并计算圆

如果您期望每个数据点的正态分布、独立转换,那么最小均方算法应该是最优的。数据点应符合以下等式:

(x - xm)^2 + (y - ym)^2 = r^2
其中,
xm
ym
r
未知,因此:

x^2 - 2*x*xm + xm^2 + y^2 - 2*y*ym + ym^2 = r^2
r^2-xm^2-ym^2
代替
c
,你就有了一个超定的线性方程组:

2*x*xm + 2*y*ym = c - x^2 - y^2
任何好的线性代数库(如IPP)都可以为您解决这个问题


如果数据中存在异常值,我建议使用RANSAC策略找到非异常值点集,然后使用上述算法找到该集的准确中心。

如果圆的半径已知(且恒定),则要以亚像素精度找到圆的中心,我使用以下方法:

  • 拍摄一张带有一个圆圈的图像(参考下面的标记)。其半径应与要查找的圆的半径相同
  • 检测测试图像和翻转标记图像中的边缘(Sobel梯度的大小,然后是一些阈值以移除低强度边缘)。在此阶段,我不应用边缘细化,也不确定边缘上的精确点
  • 将测试图像的边缘与翻转标记的边缘交叉关联。你会在中心所在的地方看到一些山峰
  • 以亚像素精度查找峰值中心。质心或拟合二维高斯钟可能会很好
  • 添加与标记中圆心的已知位置相对应的偏移
  • 否则,如果已知圆上的点具有足够的精度,则最小均方拟合应能解决找到圆心的问题(请参见@nikie的答案)。

    看一看。它可以用于。

    一种使用图像变换和聚类的算法
    我制定了一个小算法,使用图像变换和一些统计数据来检测你的圆。让我们看看它是否符合您的错误预期。
    任何好的图像和统计库都可以,我用Mathematica实现了它

    运行如下:

    一,。导入图像并运行底帽变换

    我们开始试着隔离这些圆圈。具有Box Matrix内核的。几乎所有的图像库都带有已经实现的算法

    a = Import@"http://i.stack.imgur.com/hiSjj.png";   
    b = BottomHatTransform[Binarize@a, BoxMatrix[30]]  
    
    结果是

    二,。运行命中-未命中变换以隔离圆

    擅长于寻找定义良好的几何对象。它也很容易编程,并且几乎总是出现在图像库中

    c = Binarize@HitMissTransform[b, DiskMatrix[20]]
    
    结果是:

    而我们的圈子已经被孤立,沦为核心

    三,。仅从图像中获取白色像素

    这是一个依赖于实现的步骤,因此我不会对此进行评论

    ttflat = Flatten[Table[{i, j, ImageData[c][[i, j]]}, {i, 1232}, {j, 1624}], 1];  
    ttfilter = Select[ttflat, #[[3]] == 1 &];  
    
    让我们看看还有多少像素

    Dimensions@ttfilter  
    {3684, 3}   
    
    剩下3684个像素,几乎每圈82个。足够做一些统计了

    三,。使用聚类分析选择每个圆

    在这里,聚类分析可能有些过分,但正如我已经实现的那样,使用它比编写新程序更容易:)。你可以自己做或者使用统计库

    ttc = FindClusters[ttfilter, 45, Method -> {"Agglomerate", "Linkage" -> "Complete"}];
    
    我们已经找到了簇,让我们找到每个簇中x和y的平均值。这些是圆的中心:

    means = N[Mean /@ ttc, 5]  
    
    结果是45个坐标的列表,如:

    {{161.67, 1180.1}, {162.75, 1108.9}, 
     {164.11, 1037.6}, {165.47, 966.19} .....  
    
    我们差不多完成了

    让我们检查一下结果。我们叠加了两幅图像,在检测到的中心周围画十字和圆圈

    ,这样您就可以了解所涉及的错误

    编辑

    我将你的表格结果与我的结果进行了比较

    假设圆是直线,我使用最小二乘拟合来追踪直线并计算残差

    从下图中,您可能会看到“M”y线比“y”更适合我们的。但这是假设圆圈对齐

    编辑2

    这些是第二幅图像中前45个圆的计算坐标。我有一个1像素的系统偏移。可能是因为我做了一些图像处理,但很容易纠正:)。。。只是在X和Y上减去一个像素

    {{51.135, 79.692}, {51.135, 179.69}, {51.135, 279.69},{51.135, 379.69}, {51.135, 479.69},
     {51.135, 579.69}, {51.135, 679.69}, {51.135, 779.69},{51.135, 879.69}, {51.135, 979.69}, 
     {51.135, 1079.7}, {51.135, 1179.7}, {51.135, 1279.7},{51.135, 1379.7}, {51.135, 1479.7}, 
     {151.13, 79.692}, {151.13, 179.69}, {151.13, 279.69},{151.13, 379.69}, {151.13, 479.69},
     {151.13, 579.69}, {151.13, 679.69}, {151.13, 779.69},{151.13, 879.69}, {151.13, 979.69}, 
     {151.13, 1079.7}, {151.13, 1179.7}, {151.13, 1279.7},{151.13, 1379.7}, {151.13, 1479.7}, 
     {251.13, 79.692}, {251.13, 179.69}, {251.13, 279.69},{251.13, 379.69}, {251.13, 479.69}, 
     {251.13, 579.69}, {251.13, 679.69}, {251.13, 779.69},{251.13, 879.69}, {251.13, 979.69}, 
     {251.13, 1079.7}, {251.13, 1179.7}, {251.13, 1279.7},{251.13, 1379.7}, {251.13, 1479.7}}
    
    这是图像:


    OpenCV 2.4.6.0具有在网格中查找圆心的功能。

    嗯,我以前读过Hough变换。我知道它是用来检测圆的,但是你知道在确定圆心时可以达到什么样的近似精度吗?@Marcin它取决于你离散圆心/半径空间的方式。好的是你可以利用相邻的圆圈,因为它们在一条线上,距离相等。只需添加圆中心线的参数
    {{51.135, 79.692}, {51.135, 179.69}, {51.135, 279.69},{51.135, 379.69}, {51.135, 479.69},
     {51.135, 579.69}, {51.135, 679.69}, {51.135, 779.69},{51.135, 879.69}, {51.135, 979.69}, 
     {51.135, 1079.7}, {51.135, 1179.7}, {51.135, 1279.7},{51.135, 1379.7}, {51.135, 1479.7}, 
     {151.13, 79.692}, {151.13, 179.69}, {151.13, 279.69},{151.13, 379.69}, {151.13, 479.69},
     {151.13, 579.69}, {151.13, 679.69}, {151.13, 779.69},{151.13, 879.69}, {151.13, 979.69}, 
     {151.13, 1079.7}, {151.13, 1179.7}, {151.13, 1279.7},{151.13, 1379.7}, {151.13, 1479.7}, 
     {251.13, 79.692}, {251.13, 179.69}, {251.13, 279.69},{251.13, 379.69}, {251.13, 479.69}, 
     {251.13, 579.69}, {251.13, 679.69}, {251.13, 779.69},{251.13, 879.69}, {251.13, 979.69}, 
     {251.13, 1079.7}, {251.13, 1179.7}, {251.13, 1279.7},{251.13, 1379.7}, {251.13, 1479.7}}