【问题标题】:The best circle fitting algorithm最佳圆拟合算法
【发布时间】:2010-12-08 12:37:22
【问题描述】:

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

编辑: 校准目标可以定位在视野的任何区域。以下是我使用 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  

已编辑:数字生成的模型和中心的真实坐标:

51,1    79,8
51,1    179,8
51,1    279,8
51,1    379,8
51,1    479,8
51,1    579,8
51,1    679,8
51,1    779,8
51,1    879,8
51,1    979,8
51,1    1079,8
51,1    1179,8
51,1    1279,8
51,1    1379,8
51,1    1479,8
151,1   79,8
151,1   179,8
151,1   279,8
151,1   379,8
151,1   479,8
151,1   579,8
151,1   679,8
151,1   779,8
151,1   879,8
151,1   979,8
151,1   1079,8
151,1   1179,8
151,1   1279,8
151,1   1379,8
151,1   1479,8
251,1   79,8
251,1   179,8
251,1   279,8
251,1   379,8
251,1   479,8
251,1   579,8
251,1   679,8
251,1   779,8
251,1   879,8
251,1   979,8
251,1   1079,8
251,1   1179,8
251,1   1279,8
251,1   1379,8
251,1   1479,8
351,1   79,8
351,1   179,8
351,1   279,8
351,1   379,8
351,1   479,8
351,1   579,8
351,1   679,8
351,1   779,8
351,1   879,8
351,1   979,8
351,1   1079,8
351,1   1179,8
351,1   1279,8
351,1   1379,8
351,1   1479,8
451,1   79,8
451,1   179,8
451,1   279,8
451,1   379,8
451,1   479,8
451,1   579,8
451,1   679,8
451,1   779,8
451,1   879,8
451,1   979,8
451,1   1079,8
451,1   1179,8
451,1   1279,8
451,1   1379,8
451,1   1479,8
551,1   79,8
551,1   179,8
551,1   279,8
551,1   379,8
551,1   479,8
551,1   579,8
551,1   679,8
551,1   779,8
551,1   879,8
551,1   979,8
551,1   1079,8
551,1   1179,8
551,1   1279,8
551,1   1379,8
551,1   1479,8
651,1   79,8
651,1   179,8
651,1   279,8
651,1   379,8
651,1   479,8
651,1   579,8
651,1   679,8
651,1   779,8
651,1   879,8
651,1   979,8
651,1   1079,8
651,1   1179,8
651,1   1279,8
651,1   1379,8
651,1   1479,8
751,1   79,8
751,1   179,8
751,1   279,8
751,1   379,8
751,1   479,8
751,1   579,8
751,1   679,8
751,1   779,8
751,1   879,8
751,1   979,8
751,1   1079,8
751,1   1179,8
751,1   1279,8
751,1   1379,8
751,1   1479,8
851,1   79,8
851,1   179,8
851,1   279,8
851,1   379,8
851,1   479,8
851,1   579,8
851,1   679,8
851,1   779,8
851,1   879,8
851,1   979,8
851,1   1079,8
851,1   1179,8
851,1   1279,8
851,1   1379,8
851,1   1479,8
951,1   79,8
951,1   179,8
951,1   279,8
951,1   379,8
951,1   479,8
951,1   579,8
951,1   679,8
951,1   779,8
951,1   879,8
951,1   979,8
951,1   1079,8
951,1   1179,8
951,1   1279,8
951,1   1379,8
951,1   1479,8
1051,1  79,8
1051,1  179,8
1051,1  279,8
1051,1  379,8
1051,1  479,8
1051,1  579,8
1051,1  679,8
1051,1  779,8
1051,1  879,8
1051,1  979,8
1051,1  1079,8
1051,1  1179,8
1051,1  1279,8
1051,1  1379,8
1051,1  1479,8
1151,1  79,8
1151,1  179,8
1151,1  279,8
1151,1  379,8
1151,1  479,8
1151,1  579,8
1151,1  679,8
1151,1  779,8
1151,1  879,8
1151,1  979,8
1151,1  1079,8
1151,1  1179,8
1151,1  1279,8
1151,1  1379,8
1151,1  1479,8

【问题讨论】:

  • 请提供您要匹配的圈子的示例图片。此外,带有不匹配圆圈的图像将有助于了解问题所在。
  • 请发布您的示例图像的预期中心位置以比较结果。
  • 嗯,我的意思是我已经发布的图像包含“蛋形”。也许我只是夸大了这个问题,那个相机不能把圆圈看作是理想的圆圈。我将在几分钟后发布具有已知中心位置的模型图像,以测试您的程序。
  • +1 迷幻圆点图像! :)

标签: image-processing geometry computer-vision


【解决方案1】:

一种使用图像变换和聚类的算法


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

运行如下:

1. 导入您的图像并运行底帽变换

我们开始尝试隔离圈子。带有 Box Matrix 内核的 Bottom Hat Transform 有帮助。几乎所有图像库都带有已经实现的算法。

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

结果是

2. 运行 Hit Miss Transform 以隔离圆圈

The Hit Miss Transform 擅长寻找定义明确的几何对象。它也很容易编程,并且几乎总是存在于图像库中。

c = Binarize@HitMissTransform[b, DiskMatrix[20]]

结果是:

而且我们的圈子已经被孤立并缩小到它们的核心。

3. 只从图像中获取白色像素

这是一个依赖于实现的步骤,所以我不会对此发表评论。

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 个。做一些统计就够了。

3. 使用聚类分析挑选每个圆圈

集群分析在这里可能有点过头了,但正如我已经实现的那样,使用它比编写新的东西更容易:)。您可以自己做或使用统计资料库。

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} .....  

我们差不多完成了。

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

Click to enlarge,因此您可能会了解所涉及的错误。

HTH!

编辑

我将您表格中的结果与我的结果进行了比较。

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

从下面的图表中,您可能会看到“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}}

这是图片:

【讨论】:

  • 非常感谢您的回答,您在这里付出了很多。我在主条目中发布了我取得的最佳结果(应该是最准确的)。我不知道实际值,因为这不是数值模型。我也可以发布模型的图片,但这可能不可靠,因为在相机的真实数据中,圆圈不是实际的圆圈,而是一种“蛋形”。
  • @Marcin 请张贴几张你的“蛋形”图片(不是双关语),让我们看看能不能找到任何东西
  • 嗯,我的意思是我已经发布的图像包含“蛋形”。也许我只是夸大了这个问题,那个相机不能把圆圈看作是理想的圆圈。我将在几分钟后发布具有已知中心位置的模型图像,以测试您的程序。
  • 圆圈是对齐的,看起来你的结果更准确。如果您能分析数值数据并发布中心坐标,我将不胜感激。
  • 谢谢。我实现的最佳算法在数值数据方面稍好一些(“x”轴大约 0.01 px,“y”轴大约 0.06 px)。另一方面,你的算法在真实数据上似乎更好......这里我们遇到了另一个问题 - >如何为这种类型的测试模拟可靠的模型。我尝试使用 Blender 来渲染数值模型的图像(使用不失真的镜头)。在 Blender 中,我可以使用精确的远距离标记轻松地为 3D 校准目标建模,但我无法在渲染图像的像素坐标中以亚像素精度锚定这个圆圈。
【解决方案2】:

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

如果您期望每个数据点的正态分布独立平移,那么最小均方算法应该是最佳的。数据点应符合方程:

(x - xm)^2 + (y - ym)^2 = r^2

其中xmymr 是未知的,所以:

x^2 - 2*x*xm + xm^2 + y^2 - 2*y*ym + ym^2 = r^2

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

2*x*xm + 2*y*ym = c - x^2 - y^2

任何好的线性代数库(例如 IPP)都可以为您解决这个问题。

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

【讨论】:

  • 问题是,图像数据来自相机。我正在捕获包含一组圆形标记的校准目标的图像。二值化后,边缘不必均匀分布在中心周围。此外,当从一个角度观察一个圆圈时,这个圆圈会变成一个“蛋”。也许应该采用另一个模型(不是圆形)来近似中心?
  • 最小二乘拟合给出了与简单质心算法相似的结果。似乎它的方法不够好。
  • 如果失真是由光学器件引起的,而且它们很重要,那么您需要做的第一件事就是校准和消除失真(可能还需要校正)图像。如果您使用 OpenCV,请参阅 opencv.willowgarage.com/documentation/…。然后你可以应用你喜欢的任何圆匹配算法。
  • @Marcin 如果相机倾斜,你不应该匹配一个圆圈......另外,如果这是一个相机校准程序,我建议在问题中明确说明。
  • 这是一种测量系统校准程序,是在标准相机校准之后进行的。我在第一个条目中发布了一个示例图像。
【解决方案3】:

如果圆的半径是已知的(并且是恒定的),要找到具有亚像素精度的圆心,我使用这种方法:

  1. 拍摄带有单个圆圈的图像(以下称为标记)。其半径应与您要查找的圆的半径相同。
  2. 检测测试图像和翻转标记图像中的边缘(Sobel 梯度的大小,然后是一些阈值以去除低强度边缘)。在这个阶段我没有应用边缘细化,也没有识别边缘上的确切点。
  3. 将测试图像的边缘与翻转标记的边缘交叉关联。您会在中心所在的位置看到一些山峰。
  4. 以亚像素精度查找峰的中心。质心或拟合 2D 高斯钟可能效果很好。
  5. 添加与标记中圆心的已知位置相对应的移位。

否则,如果圆上的点已知足够准确,最小均方拟合应该可以解决寻找中心的问题(请参阅@nikie 的回答)。

【讨论】:

    【解决方案4】:

    看看Hough transform。可用于detect circles

    【讨论】:

    • 嗯,我以前读过霍夫变换。我知道它是用来检测圆的,但是你知道中心确定可以达到什么近似精度吗?
    • @Marcin 这取决于您离散中心/半径空间的方式。好处是您可以利用相邻的圆圈,因为它们在一条线上且等距。只需将圆心所在的线的参数添加到霍夫空间即可。
    【解决方案5】:

    OpenCV 2.4.6.0 具有findCirclesGrid 函数来查找网格中的圆心。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多