简体   繁体   English

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

[英]How to find the pixel that is farthest from another in the same pixel group

By "Group", I mean a set of pixels such that every pixel at least have one adjacent pixel in the same set, the drawing shows an example of a group. “组”是指一组像素,使得每个像素至少在同一组中具有一个相邻像素,该图示出了组的示例。

一个小组的例子

I would like to find the pixel which is having the greatest straight line distance from a designated pixel (for example, the green pixel). 我想找到与指定像素(例如,绿色像素)具有最大直线距离的像素。 And the straight line connecting the two pixels (the red line) must not leave the group. 并且连接两个像素的直线(红线)不得离开该组。

My solution is looping through the degrees and simulating the progress of the lines starting from the green pixel with the degree and see which line travelled the farthest distance. 我的解决方案是循环度数并模拟从绿色像素开始的线条的进度,并查看哪条线走过最远的距离。

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

It is obviously not the best algorithm. 它显然不是最好的算法。 Thus I am asking for help here. 因此,我在这里寻求帮助。

Thank you and sorry for my poor English. 谢谢你,对不起我的英语不好。

I wouldn't work with angles. 我不会用角度来工作。 But I'm pretty sure the largest distance will always be between two pixels at the edge of the set, thus I'd trace the outline: From any pixel in the set go to any direction until you reach the edge of the set. 但我很确定最大距离总是在集合边缘的两个像素之间,因此我会跟踪轮廓:从集合中的任何像素到任何方向,直到到达集合的边缘。 Then move (couter)clockwise along the edge. 然后顺时针沿着边缘移动(连接)。 Do this with any pixel as starting point and you'll be able to find the largest distance. 以任何像素作为起点进行此操作,您将能够找到最大距离。 It's still pretty greedy, but I thought it might give you an alternative starting point to improve upon. 它仍然相当贪婪,但我认为它可能会为你提供另一个改进的起点。

Edit: What just came to my mind: When you have a start pixel s and the end pixel e . 编辑:刚出现在我的脑海中:当你有一个起始像素s和结束像素e In the first iteration using s the corresponding e will be adjacent (the next one along the edge in clockwise direction). 在使用s的第一次迭代中,相应的e将相邻(沿着顺时针方向的边缘的下一个)。 As you iterate along the edge the case might occur, that there is no straight line through the set between s and e . 当您沿边缘迭代时,可能会出现这种情况,即在se之间没有直线穿过该集合。 In that case the line will hit another part of the set-edge (the pixel p ) though. 在这种情况下,该线将击中设定边缘的另一部分(像素p )。 You can continue iteration of the edge at that pixel ( e = p ) 您可以继续迭代该像素的边缘( e = p

Edit2: And if you hit a p you'll know that there can be no longer distance between s and e so in the next iteration of s you can skip that whole part of the edge (between s and p ) and start at p again. 编辑2:如果你点击一个p你就会知道se之间不再有距离所以在s的下一次迭代中你可以跳过整个边缘部分( sp之间)并再次从p开始。

Edit3: Use the above method to find the first p . 编辑3:使用上面的方法找到第一个p Take that p as next s and continue. 采取p作为下一个s继续。 Repeat until you reach your first p again. 重复,直到再次达到第一个p The max distance will be between two of those p unless the edge of the set is convex in which case you wont find a p . 最大距离将介于两个p之间,除非该组的边缘是凸的,在这种情况下你不会找到p

Disclaimer: This is untested and are just ideas from the top of my head, no drawings have been made to substantiate my claims and everything might be wrong (ie think about it for yourself before you implement it ;D) 免责声明:这是未经测试的,只是我头脑中的想法,没有任何图纸来证实我的说法,一切都可能是错的(即在你实施之前自己考虑一下; D)

First, note that the angle discretization in your algorithm may depend on the size of the grid. 首先,请注意算法中的角度离散化可能取决于网格的大小。 If the step is too large, you can miss certain cells, if it is too small, you will end up visiting the same cell again and again. 如果步骤太大,您可能会错过某些单元格,如果它太小,您将最终一次又一次地访问同一个单元格。

I would suggest that you enumerate the cells in the region and test the condition for each one individually instead. 我建议您枚举区域中的单元格,然后单独测试每个单元格的条件。 The enumeration can be done using breadth-first or depth-first search (I think the latter would be preferable, since it will allow one to establish a lower bound quickly and do some pruning). 可以使用广度优先或深度优先搜索来完成枚举(我认为后者将是更可取的,因为它将允许快速建立下限并进行一些修剪)。

One can maintain the farthest point X found so far and for each new point in the region, check whether (a) the point is further away than the one found so far and (b) it's connected to the origin by a straight line passing through the cells of the region only. 可以保持到目前为止找到的最远点X,并且对于该区域中的每个新点,检查(a)该点是否比到目前为止发现的点更远,并且(b)它是否通过直线连接到原点。只有该地区的细胞。 If both conditions are satisfied, update the X, else go on with the search. 如果两个条件都满足,请更新X,否则继续搜索。 If condition (a) is not satisfied, condition (b) doesn't have to be checked. 如果不满足条件(a),则不必检查条件(b)。

The complexity of this solution would be O(N*M) , where N is the number of cells in the region and M is the larger dimension of the region ( max(width,height) ). 该解决方案的复杂性为O(N*M) ,其中N是区域中的单元数量, M是区域的较大尺寸( max(width,height) )。 If performance is of essence, more sophisticated heuristics can be applied, but for a reasonably sized grid this should work fine. 如果性能至关重要,可以应用更复杂的启发式算法,但对于合理大小的网格,这应该可以正常工作。

Search for pixel, not for slope. 搜索像素,而不是斜率。 Pseudocode. 伪代码。

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

You might want to sort pixels descending by |dx| 您可能希望按| dx |降序排列像素 + |dy| + | dy | before that. 在那之前。

Use a double data-structure: 使用双数据结构:

  • One that contains the pixels sorted by angle. 一个包含按角度排序的像素。
  • The second one sorted by distance (for fast access, this should also contain "pointers" for the first data structure). 第二个按距离排序(对于快速访问,这也应该包含第一个数据结构的“指针”)。

Walk through the angle sorted one, and check for each pixel that the line is within the region. 遍历角度排序的一个,并检查该行在该区域内的每个像素。 Some pixels will have the same angle, so you can walk from the origin along the line, and go till you go out from the region. 有些像素将具有相同的角度,因此您可以沿着线从原点走,直到您从该区域出去。 You can eliminate all the pixels which are beyond that point. 您可以消除超出该点的所有像素。 Also, if the maximum distance increased, remove all pixels which have a shorter distance. 此外,如果最大距离增加,请删除所有距离较短的像素。

Treat your region as a polygon instead of a collection of pixels. 将您的区域视为多边形而不是像素集合。 From this you can get a list of line segments (the edges of your polygon). 从这里你可以得到一个线段列表(多边形的边缘)。

Draw a line from your start pixel to each pixel you are checking. 从起始像素到要检查的每个像素绘制一条线。 The longest line that does not intersect any of the line segments of your polygon indicates your most distant pixel that is reachable by a straight line from your pixel. 不与多边形的任何线段相交的最长线表示可以通过像素的直线到达的最远像素。

There are various optimizations you can make to this and a few edges cases to check, but let me know if you understand the idea before i post those... in particular, do you understand what I mean by treating as a polygon instead of a collection of pixels? 您可以对此进行各种优化以及检查一些边缘情况,但如果您在发布之前了解这个想法,请告诉我...特别是,您是否理解我的意思是将其视为多边形而不是像素集合?

To add, this approach will be significantly faster than any angle based approach or approach that requires "walking" for all but the smallest collections of pixels. 另外,这种方法将明显快于任何基于角度的方法或方法,除了最小的像素集合之外,所有方法或方法都需要“行走”。 You can further optimize because your problem is equivalent to finding the most distant endpoint of a polygon edge that can be reached via an unintersected straight line from your start point. 您可以进一步优化,因为您的问题等同于找到多边形边缘的最远端点,该端点可以通过从起点开始的未反转的直线到达。 This can be done in O(N^2), where N is the number of edges. 这可以在O(N ^ 2)中完成,其中N是边数。 Note that N will be much much smaller than the number of pixels, and many of the algorithms proposed that use angles an/or pixel iteration are be going to instead depend on the number of pixels. 注意,N将比像素的数量小得多,并且提出的使用角度和/或像素迭代的许多算法将取决于像素的数量。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM