【问题标题】:Algorithms: Ellipse matching算法:椭圆匹配
【发布时间】:2016-07-02 17:30:27
【问题描述】:

我有很多像下面这样的图片(只有白色和黑色):

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

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

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

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

非常感谢

【问题讨论】:

  • 你在考虑什么语言?如果您使用“将位图转换为 svg”在谷歌上搜索许多语言名称,您可以找到一些技巧。这篇文章很有趣(作为“信息熵”的讨论):stackoverflow.com/questions/3072621/…
  • 我假设你的椭圆没有“倾斜”,对吧?
  • 我也喜欢沃尔特要去的地方。更正式地说:椭圆焦点是否具有相同的 Y 坐标值?
  • 不幸的是,椭圆可能是倾斜的(椭圆焦点可能有不同的 y 坐标值)。第一步,语言无关紧要。谢谢,关于 svg 技术的链接:)
  • @KevinMeier 椭圆总是轴对齐吗?

标签: image algorithm ellipse


【解决方案1】:
  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. 代数

      使用具有“均匀”分散已知点的椭圆方程来形成方程组来计算椭圆参数 (x0,y0,rx,ry,angle)。

    2. 几何上

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

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

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

    3. 近似搜索

      您可以在 #4 中找到的限制范围内遍历“所有”可能的椭圆参数组合,然后选择最接近您的点的那个。那将是非常缓慢的粗略,因此请使用类似于我的approx class 的方法使用二进制搜索。另见

      关于它如何用于与您的相似的合身。

    4. 混合

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

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

这就是我的想法:

【讨论】:

  • 感谢您非常详细的回答:)我会尝试实施/使用您的想法。
【解决方案2】:

你可能需要这样的东西:

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

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

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

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

B² 0)。这意味着,与圆形问题相比,您没有 3 个维度,而是 5 个维度。这导致霍夫变换要困难得多。幸运的是,您的示例表明您不需要高分辨率。


另见:algorithm for detecting a circle in an image


编辑

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

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

【讨论】:

  • 图像分辨率最高可达 512*512 像素,包含约 200 个椭圆。有时会有 10-20 个椭圆的簇,但这只是非常困难的情况。感谢您的输入:)!
【解决方案3】:

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


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

【讨论】:

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