我有一长串的xy坐标,如下所示:
>>> data = [(x1,y1),(x2,y2),(x3,y3),...]
每对坐标代表图像中轮廓的一个点,我想对它们进行排序,就好像它们沿着轮廓(最短路径)排列一样。轮廓的形状非常复杂(它是一个国家的形状),这就是ConvexHull的原因。 不会工作。
我尝试了这段代码,但不够精确:
>>> import math
>>> import matplotlib.patches as patches
>>> import pylab
>>> pp=[(1,1),(2,3),(3,4)]
# compute centroid
>>> cent=(sum([p[0] for p in pp])/len(pp),sum([p[1] for p in pp])/len(pp))
# sort by polar angle
>>> pp.sort(key=lambda p: math.atan2(p[1]-cent[1],p[0]-cent[0]))
# plot points
>>> pylab.scatter([p[0] for p in pp],[p[1] for p in pp])
# plot polyline
>>> pylab.gca().add_patch(patches.Polygon(pp,closed=False,fill=False))
>>> pylab.grid()
>>> pylab.show()
我已尝试过像this case中的建议 但它效果不好,因为我的坐标列表太长了。
由于这些点彼此非常接近this question的解决方案 对我来说可能看起来太复杂了。
答案 0 :(得分:0)
如果您的形状为“简单”,则可以计算点云的中心(X和Y的平均值)。按照从中心到点的角度对点进行排序,如果它们中的两个具有相同的角度,则按它们与中心的距离对它们进行排序。这应该可以解决问题。
center = functools.reduce(lambda p1, p2: (p1[0]+p2[0], p1[1]+p2[1]), data)
center = (center[0] / len(data), center[1] / len(data))
def angle(p1, p2):
return math.atan2(p2[1], p2[0]) - math.atan2(p1[1], p1[0])
answer = sorted(data, key=lambda p: (angle(p, center), distance(p, center)))
对于更复杂的形状,我有另一种算法叫做放气船体。从你的云的船体,你放气,直到它触及所有剩余的点:
def deflate_hull(points):
hull = convex_hull(points)
for p in hull:
points.remove(p)
while points:
l = len(hull)
_, p, i = min((distance(hull[i-1], p) + distance(p, hull[i]) - distance(hull[i-1], hull[i]), p, i)
for p in points
for i in range(l))
points.remove(p)
hull = hull[:i] + [p] + hull[i:]
return hull
def convex_hull(points):
if len(points) <= 3:
return points
upper = half_hull(sorted(points))
lower = half_hull(reversed(sorted(points)))
return upper + lower[1:-1]
def half_hull(sorted_points):
hull = []
for C in sorted_points:
while len(hull) >= 2 and turn(hull[-2], hull[-1], C) <= -1e-6:
hull.pop()
hull.append(C)
return hull
def turn(A, B, C):
return (B[0]-A[0]) * (C[1]-B[1]) - (B[1]-A[1]) * (C[0]-B[0])
def distance(p1, p2):
return math.sqrt((p1[0]-p2[0])**2 + (p1[1]-p2[1])**2)
answer = deflate_hull(data)
答案 1 :(得分:0)
您描述的问题类似于寻找凸包。你可以看看here
答案 2 :(得分:0)
更新: 同时我通过使用OpenCV的findContours解决了它 - 它输出了像我一样的坐标!