如何在同一像素组中找到距离另一个像素最远的像素

时间:2012-09-20 10:00:34

标签: algorithm pixel distance point

“组”是指一组像素,使得每个像素在同一组中至少有一个相邻像素,图中显示了一个组的示例。

An example of a group

我想找到与指定像素(例如,绿色像素)具有最大直线距离的像素。并且连接两个像素的直线(红线)不得离开该组。

我的解决方案是循环度数并模拟从绿色像素开始的线条的进度,并查看最远距离的哪条线。

longestDist = 0
bestDegree = -1
farthestX = -1
farthestY = -1
FOR EACH degree from 0 to 360
    dx=longestDist * cos(degree);
    dy=longestDist * sin(degree);
    IF Point(x+dx , y+dy) does not belong to the group
        Continue with next degree
        //Because it must not be the longest line, so skip it
    END IF
    (farthestX , farthestY) = simulate(x,y,degree)
    d = findDistance(x , y , farthestX , farthestY)
    IF d > longestDist
        longestDist = d
        bestDegree = degree
    END IF
END FOR

这显然不是最好的算法。因此,我在这里寻求帮助。

谢谢你,对不起我的英语不好。

5 个答案:

答案 0 :(得分:1)

我不会使用角度。但我很确定最大距离总是在集合边缘的两个像素之间,因此我会跟踪轮廓:从集合中的任何像素到任何方向,直到到达集合的边缘。然后顺时针沿着边缘移动(连接)。以任何像素作为起点进行此操作,您将能够找到最大距离。它仍然相当贪婪,但我认为它可能会为你提供另一个改进的起点。

编辑:刚出现在我的脑海中:当您有一个起始像素s和结束像素e时。在使用s的第一次迭代中,相应的e将相邻(顺时针方向沿着边缘的下一个)。当您沿着边缘迭代时,可能会发生这种情况,se之间的集合没有直线。在这种情况下,该行将击中集合边的另一部分(像素p)。您可以继续在该像素(e = p

处迭代边缘

编辑2:如果您点击p,您就会知道se之间的距离不再相同,所以在s的下一次迭代中你可以跳过整个边缘部分(sp之间)并再次从p开始。

编辑3:使用上述方法查找第一个p。将p作为下一个s并继续。重复,直到再次到达第一个p。最大距离将介于其中两个p之间,除非该集合的边缘是凸的,在这种情况下您将找不到p

免责声明:这是未经测试的,只是我头脑中的想法,没有任何图纸来证实我的说法,一切都可能是错的(即在你实施之前自己考虑一下; D)

答案 1 :(得分:0)

首先,请注意算法中的角度离散化可能取决于网格的大小。如果步骤太大,您可能会错过某些单元格,如果它太小,您将最终一次又一次地访问同一单元格。

我建议您枚举区域中的单元格,然后单独测试每个单元格的条件。可以使用广度优先或深度优先搜索来完成枚举(我认为后者将是更可取的,因为它将允许快速建立下限并进行一些修剪)。

可以保持到目前为止找到的最远点X,并且对于该区域中的每个新点,检查(a)该点是否远远超过到目前为止发现的点和(b)它是否与仅通过直线穿过该区域的细胞。如果两个条件都满足,请更新X,否则继续搜索。如果不满足条件(a),则不必检查条件(b)。

此解决方案的复杂性为O(N*M),其中N是区域中的单元格数,M是区域的较大维度(max(width,height)) 。如果性能至关重要,可以应用更复杂的启发式算法,但对于合理大小的网格,这应该可以正常工作。

答案 2 :(得分:0)

搜索像素,而不是斜率。伪代码。

bestLength = 0
for each pixel in pixels
  currentLength = findDistance(x, y, pixel.x, pixel.y)
  if currentLength > bestLength
    if goodLine(x, y, pixel.x, pixel.y)
      bestLength = currentLength
      bestX = pixel.x
      bestY = pixel.y
    end
  end
end

您可能希望按| dx |降序排列像素+ | dy |在那之前。

答案 3 :(得分:0)

使用双数据结构:

  • 包含按角度排序的像素的文件。
  • 第二个按距离排序(对于快速访问,这也应该包含第一个数据结构的“指针”)。

遍历角度排序的一个,并检查该行在该区域内的每个像素。有些像素将具有相同的角度,因此您可以沿着线从原点走,直到您从该区域出去。您可以消除超出该点的所有像素。此外,如果最大距离增加,请删除所有距离较短的像素。

答案 4 :(得分:0)

将您的区域视为多边形而不是像素集合。从这里你可以得到一个线段列表(多边形的边缘)。

从起始像素到您正在检查的每个像素绘制一条线。不与多边形的任何线段相交的最长线表示可以通过像素的直线到达的最远像素。

您可以对此进行各种优化以及检查一些边缘情况,但如果您在发布之前了解这个想法,请告诉我...特别是,您是否明白我的意思是将其视为多边形而不是像素集合?

要添加,这种方法将明显快于任何基于角度的方法或方法,除了最小的像素集合之外,所有方法或方法都需要“行走”。您可以进一步优化,因为您的问题等同于找到多边形边缘的最远端点,该端点可以通过从起点开始的未反转的直线到达。这可以在O(N ^ 2)中完成,其中N是边数。请注意,N将比像素数小得多,并且许多使用角度和/或像素迭代的算法将取决于像素数。