连接点 - 连接轮廓点之间的线

时间:2010-08-16 12:32:27

标签: java algorithm contour

我有64x64的灰度图像。我通过一个简单的算法找到了轮廓的点:

  • 找到最亮点(例如:100)
  • 除以2(100/2 = 50)
  • 在结果周围定义一个条带(50-5 = 45到50 + 5 = 55)
  • 标记在乐队中有价值的所有点(45到55之间)

现在的问题是,我如何确定连接点的顺序?

(所有参考文献都将被接受,链接,想法等)

6 个答案:

答案 0 :(得分:4)

您的算法允许整个图像(保存为一个像素)为“轮廓”。我不确定这究竟是你想要的;通常轮廓是两个不同区域之间的边界。您的方法的问题是您可以获得没有特别明显的遍历顺序的巨大像素块。如果您的轮廓厚度为单个像素,则遍历顺序更加明显:顺时针或逆时针。

请考虑以下图片。

........
..%%%%..
.%%%%...
...%%%%.
....%...
........

在这里,我将所有“黑暗”(可能都是< 50,或许)标记为%,并将所有内容标记为.。现在你可以选择两个区域之间边界上的任何像素(我会选择黑暗面;你也可以在光线侧绘制轮廓,或者在光明和黑暗面之间直接绘制更多的工作。 )

........
..%%%%..
.*%%%...
...%%%%.
....%...
........

现在,您尝试沿着暗区域的外边缘,一次一个像素。首先,你看一下明亮的方向(例如直接离开)。然后你转动 - 逆时针旋转,比方说 - 直到你遇到一个黑暗的像素。

........
..%%%%..
1*5%%...
234%%%%.
....%...
........

一旦你到达位置5,就会发现它很暗。因此,您将其标记为轮廓的一部分,然后尝试通过从刚刚来自的像素开始扫描来找到轮廓上的下一个部分

........
..%%%%..
.0*%%...
.123%%%.
....%...
........

0来自1你来自哪里 - 你不会回到那里 - 然后你尝试像素23(两个光,这是不行的),直到你点击像素@,这是黑暗的。

通过这种方式,您可以逐个像素地遍历轮廓 - 既识别轮廓又获得像素的顺序 - 直到您与开始的相同像素碰撞并且将离开从它那里,你可以击中你第一次离开它时所做的像素。然后关闭轮廓。在我们的例子中,我们正在制作一个8连通的轮廓(即我们看8个邻居,而不是4个),我们得到以下结果(其中........ ..@@@@.. .@@%@... ...@%@@. ....@... ........ 表示轮廓点)。

{{1}}

(你必须有这个两行标准,或者如果你有一个像素宽的黑暗区域,你会向上走,但不能沿着它向后走。)

此时,您已经涵盖一个整个边界。但可能还有其他人。继续寻找浅色像素旁边的暗像素,直到在所有像素的顶部绘制轮廓。现在,您已将两级图像(暗和亮像素)转换为一组轮廓。

如果轮廓最终太嘈杂,请考虑先模糊图像。这将使轮廓平滑。 (或者,您可以先找到轮廓,然后用移动窗口平均坐标。)

答案 1 :(得分:1)

通常,一组给定的点可以多种方式连接以形成不同的形状。

例如,考虑一组由正方形的角和其中心组成的5个点。这些点可以连接成一个正方形,一边“凹入”到中心。但哪一方呢?没有独特的答案。

其他形状可能更加复杂,没有明显的方法来连接点。

如果您允许将点数集减少到convex hull,则会更容易。

答案 2 :(得分:1)

我还尝试创建一种将轮廓点连接到平滑曲线的算法。查看我的开源项目http://outliner.codeplex.com。 这个想法与FUZxxl提出的相同,但我不理解他对复杂性的担忧:处理时间与所有轮廓笔划的总长度成正比。

答案 3 :(得分:0)

我不知道收集这些积分是否会让你走得更远。 (我可以想出几乎不可能知道他们应该进入哪个顺序的情况。)

如何到达最亮点。
转到亮点,例如,围绕此点的360点,例如5像素 从那里继续,但请确保你不要回到你来自的地方:)

答案 4 :(得分:0)

也许试试:

  1. 开始
  2. 找到最近的点b
  3. 连接a b
  4. 等等。
  5. 可能不好,因为复杂性就像O(n²)。你可以通过仅查看开始附近的点来简化这一点,正如aioobe建议的那样。这个算法很好,如果这些点彼此相差2-3px,但可能会产生非常奇怪的网格。

答案 5 :(得分:0)

另见Flood fill 和SO下的可爱小程序 mapping-a-branching-tile-path