算法:椭圆匹配

时间:2016-03-16 17:07:35

标签: image algorithm ellipse

我有很多像以下图片(只有白色和黑色):

enter image description here

我最后的问题是找到匹配良好的椭圆。不幸的是,真正使用过的图像并不总是那么好看。它们可能会变形一些,这使得椭圆匹配可能更难。

我的想法是找到“断点”。我在下图中标记了它们:

enter image description here

也许这些点可以帮助匹配省略号。最终结果应该是这样的:

enter image description here

有人知道可以使用什么算法来找到这些断点吗?或者甚至更好地进行良好的椭圆匹配?

非常感谢

3 个答案:

答案 0 :(得分:3)

  1. 采样圆周点

    只需扫描图像,然后选择任何白色邻居的全黑像素。您可以通过将剩余的黑色像素重新着色为任何未使用的颜色(蓝色)来实现此目的。

    完成整个图像后,您可以将内部背面从未使用的颜色(蓝色)重新着色为白色。

  2. 形成每个簇/椭圆的有序圆周点列表

    只需扫描图像即可找到第一个黑色像素。然后使用A*对圆周点进行排序,并将路径存储在某个数组或列表pnt[]中,并将其作为圆形数组处理。

  3. 找到"断点"

    可以通过找到的点的邻居之间的角度的峰值来检测它们。

    之类的东西
    float a0=atan2(pnt[i].y-pnt[i-1].y,pnt[i].x-pnt[i-1].x);
    float a1=atan2(pnt[i+1].y-pnt[i].y,pnt[i+1].x-pnt[i].x);
    float da=fabs(a0-a1); if (da>M_PI) da=2.0*M_PI-da;
    if (da>treshold) pnt[i] is break point;
    

    或使用在断点处斜率角度变化符号的事实:

    float a1=atan2(pnt[i-1].y-pnt[i-2].y,pnt[i-1].x-pnt[i-2].x);
    float a1=atan2(pnt[i  ].y-pnt[i-1].y,pnt[i  ].x-pnt[i-1].x);
    float a2=atan2(pnt[i+1].y-pnt[i  ].y,pnt[i+1].x-pnt[i  ].x);
    float da0=a1-a0; if (da0>M_PI) da0=2.0*M_PI-da0; if (da0<-M_PI) da0=2.0*M_PI+da0;
    float da1=a2-a1; if (da1>M_PI) da1=2.0*M_PI-da1; if (da1<-M_PI) da1=2.0*M_PI+da1;
    if (da0*da1<0.0) pnt[i] is break point;
    
  4. 适合省略号

    所以如果没有发现断点,你可以将整个pnt []作为单个椭圆。例如,查找边界框。它的中心是椭圆的中心,它的大小为你提供了半轴。

    如果发现断点,则首先找到整个pnt[]的边界框,以获得半轴和中心位置区域搜索的限制。然后将pnt[]除以断点之间的部分。将每个零件作为椭圆的单独部分处理并适合。

    在所有pnt[]部分拟合之后,检查一些椭圆是否相同,例如,如果它们与另一个椭圆重叠,它们将被分割......所以合并相同的部分(或平均值以提高精度) )。然后将所有pnt[i]点重新着色为白色,清除pnt[]列表并循环#2 ,直到找不到更多黑色像素。

  5. 如何根据选择点拟合椭圆?

    1. <强>代数

      使用椭圆方程和&#34;均匀&#34;分散已知点以形成方程组来计算椭圆参数(x0,y0,rx,ry,angle)。

    2. <强>几何

      例如,如果您检测到坡度为0,90,180或270度,那么您将处于与周长的半轴交叉处。因此,如果您有两个这样的点(每个半轴一个),那么您需要进行拟合(如果它是轴对齐的椭圆)。

      对于非轴对齐的椭圆,您需要有足够大的圆周部分。您可以利用边界框中心也是椭圆中心的事实。所以,如果你得到整个椭圆,你也知道中心。可以检测具有最大和最小切线变化的具有圆周的半轴交点。如果你有中心和两点你所需要的一切。如果你只有部分中心(只有x或y坐标),你可以结合更多的轴点(找到3或4)...或近似丢失的信息。

      半H,V​​线轴也与椭圆中心相交,因此如果不是pnt[]列表中的整个椭圆,它可用于检测它。

      non-axis-aligned ellipse fit

    3. 近似搜索

      你可以遍历&#34;所有&#34;椭圆参数的可能组合在#4 中的限制范围内,并选择最接近您的点的那个。这会非常慢,所以使用二分搜索就像我的approx class之类的方法。另见

      如何使用它与你的相似。

    4. <强>混合

      您可以结合几何和近似方法。首先通过几何方法计算出你能做到的。然后用近似搜索计算其余部分。您还可以提高找到的值的精确度。

    5. 在极少数情况下合并两个椭圆而没有断点时,拟合的椭圆将与您的点不匹配。因此,如果检测到这种情况,您必须将使用的点细分为组,直到它们符合匹配...

      这就是我对此的想法:

      overview

答案 1 :(得分:2)

你可能需要这样的东西:

https://en.wikipedia.org/wiki/Circle_Hough_Transform

您的边缘点只是黑色像素,至少有一个白色4邻居。

但不幸的是,你说你的椭圆可能会“倾斜”。通用椭圆由二次方程描述,如

x² + Ay² + Bxy + Cx + Dy + E = 0

B²&lt; 4A(⇒A> 0)。这意味着,与圆形问题相比,您没有3个维度而是5.这会导致Hough变换更加困难。幸运的是,您的示例表明您不需要高分辨率。

另请参阅:algorithm for detecting a circle in an image

修改

算法的上述想法是too optimistic,至少如果以直接的方式应用的话。好消息是,似乎两个聪明人(谢永红和强吉)已经为我们完成了这项功课:

https://www.ecse.rpi.edu/~cvrl/Publication/pdf/Xie2002.pdf

答案 2 :(得分:1)

我不确定我是否会创建自己的算法。为什么不利用其他团队所做的工作来弄清楚位图的所有曲线拟合?


INKSCAPE (App Link)

Inkscape是一个开源工具,专门用于矢量图形编辑,并具有处理光栅(位图)部分的能力。

以下链接指向Inkscape API的起点:

http://wiki.inkscape.org/wiki/index.php/Script_extensions

看起来您可以在Inkscape中编写脚本,或通过外部脚本访问Inkscape。

您也可以使用inkscape命令行界面执行零脚本操作:

http://wiki.inkscape.org/wiki/index.php/Frequently_asked_questions#Can_Inkscape_be_used_from_the_command_line.3F


COREL DRAW (App Link)

Corel Draw被公认为矢量图形的首选行业解决方案,并且有一些很棒的工具可以将光栅化图像转换为矢量图像。

这是指向其API的链接:

https://community.coreldraw.com/sdk/api

这里是Corel Draw批量图像处理(非脚本解决方案)的链接:

http://howto.corel.com/en/c/Automating_tasks_and_batch-processing_images_in_Corel_PHOTO-PAINT