对给定模式中的以下坐标进行排序:
Posted
技术标签:
【中文标题】对给定模式中的以下坐标进行排序:【英文标题】:Sorting the following coordinates in the given pattern: 【发布时间】:2016-07-09 01:26:42 【问题描述】:我有以下图片:
图像中白色斑点对应的坐标按照x坐标的递增值排序。但是,我希望他们遵循以下模式:
(从左下角到左上角呈锯齿形。)
任何线索我该怎么做?任何有关该算法的线索将不胜感激。
坐标集如下:
[46.5000000000000,104.500000000000]
[57.5000000000000,164.500000000000]
[59.5000000000000,280.500000000000]
[96.5000000000000,66.5000000000000]
[127.500000000000,103.500000000000]
[142.500000000000,34.5000000000000]
[156.500000000000,173.500000000000]
[168.500000000000,68.5000000000000]
[175.500000000000,12.5000000000000]
[198.500000000000,37.5000000000000]
[206.500000000000,103.500000000000]
[216.500000000000,267.500000000000]
[225.500000000000,14.5000000000000]
[234.500000000000,62.5000000000000]
[251.500000000000,166.500000000000]
[258.500000000000,32.5000000000000]
[271.500000000000,13.5000000000000]
[284.500000000000,103.500000000000]
[291.500000000000,61.5000000000000]
[313.500000000000,32.5000000000000]
[318.500000000000,10.5000000000000]
[320.500000000000,267.500000000000]
[352.500000000000,57.5000000000000]
[359.500000000000,102.500000000000]
[360.500000000000,167.500000000000]
[366.500000000000,11.5000000000000]
[366.500000000000,34.5000000000000]
[408.500000000000,9.50000000000000]
[414.500000000000,62.5000000000000]
[419.500000000000,34.5000000000000]
[451.500000000000,12.5000000000000]
[456.500000000000,97.5000000000000]
[457.500000000000,168.500000000000]
[465.500000000000,62.5000000000000]
[465.500000000000,271.500000000000]
[468.500000000000,31.5000000000000]
[498.500000000000,10.5000000000000]
[522.500000000000,105.500000000000]
[524.500000000000,32.5000000000000]
[533.500000000000,60.5000000000000]
[534.500000000000,11.5000000000000]
[565.500000000000,164.500000000000]
[576.500000000000,33.5000000000000]
[581.500000000000,10.5000000000000]
[582.500000000000,67.5000000000000]
[586.500000000000,267.500000000000]
[590.500000000000,102.500000000000]
[622.500000000000,10.5000000000000]
[630.500000000000,32.5000000000000]
[646.500000000000,58.5000000000000]
[653.500000000000,94.5000000000000]
[669.500000000000,8.50000000000000]
[678.500000000000,167.500000000000]
[680.500000000000,31.5000000000000]
[705.500000000000,57.5000000000000]
[719.500000000000,9.50000000000000]
[729.500000000000,271.500000000000]
[732.500000000000,33.5000000000000]
[733.500000000000,97.5000000000000]
[757.500000000000,11.5000000000000]
[758.500000000000,59.5000000000000]
[778.500000000000,157.500000000000]
[792.500000000000,31.5000000000000]
[802.500000000000,10.5000000000000]
[812.500000000000,94.5000000000000]
[834.500000000000,59.5000000000000]
[839.500000000000,30.5000000000000]
[865.500000000000,160.500000000000]
[866.500000000000,272.500000000000]
[885.500000000000,58.5000000000000]
[892.500000000000,97.5000000000000]
[955.500000000000,94.5000000000000]
[963.500000000000,163.500000000000]
[972.500000000000,265.500000000000]
【问题讨论】:
@JorensM 你有效率限制吗?对于示例中的小尺寸值,O(N^2) 算法看起来足够高效,正如当前答案中提出的那样。 @JorensM 您能否准确说明您在寻找什么 【参考方案1】:根据 uSemSurprise 的回答,我将采用 3 步方法:
按y-coord
对点列表进行排序。这是 O(n log n)
确定y-axis
范围。我只是遍历这些点并记下y-coord
差异大于阈值的位置。这当然是 O(n)
按x-coord
对代表y-axis
行的每个子列表进行排序。如果我们有 m
子列表 k
每个项目,这将是 O(m (k log k));所以整个过程还是O(n log n)
代码:
def zigzag(points, threshold=10.0)
#step 1
points.sort(key=lambda x:x[1])
#step 2
breaks = []
for i in range(1, len(points)):
if points[i][1] - points[i-1][1] > threshold:
breaks.append(i)
breaks.append(i)
#step 3
rev = False
start = 0
outpoints = []
for b in breaks:
outpoints += sorted(points[start:b], reverse = rev)
start = b
rev = not rev
return outpoints
【讨论】:
点 1 和 2 可以用 y 坐标上的直方图代替,然后识别峰值并以这种方式分割 y 轴。可能是更复杂的代码,但对于大量的点集合会更好地扩展。【参考方案2】:你可以对y-axis
坐标对应的x-axis
坐标进行排序,这里你认为一定的y-axis
范围,即按照x-axis
排序的坐标都属于同一个y-axis
范围。每次向上移动到不同的 y-axis
范围时,您都可以翻转排序顺序,即先增加后减少,依此类推。
【讨论】:
【参考方案3】:我能想到的最相似的算法是 Andrew 的凸包算法,特别是下包(虽然取决于坐标系,您可能需要改用上包)。
运行 lower hull 算法并删除点直到没有剩余点会得到你想要的。要获得之字形图案,请在每隔一次运行时颠倒顺序。
这是大多数语言的实现:
https://en.wikibooks.org/wiki/Algorithm_Implementation/Geometry/Convex_hull/Monotone_chain
编辑:在模糊测量的情况下,缺点是精度。如果凸包不是您所需要的,您可能需要稍微调整算法。 IE:如果你想认为它仍然是船体的一部分,如果它在 0.1 以内,或者说 1% 在船体上等等。在给出的示例中,坐标正好在线上,所以它会很好地工作,但如果坐标是随机分布在它们实际位置的 0.1 范围内,则效果不会那么好。
【讨论】:
【参考方案4】:这种方法假设您知道预期的行数,尽管我怀疑您可以通过编程方式来估算。
nbins = 6; % Number of horizontal rows we expect
[bin,binC] = kmedoids(A(:,2),nbins); % Use a clustering approach to group them
bin = binC(bin); % Clusters in random order, fix it so that clusters
[~,~,bin] = unique(bin); % are ordered by central y value
xord = A(:,1) .* (-1).^mod(bin+1,2); % flip/flop for each row making the x-coord +ve or -ve
% so that we can sort in a zig-zag
[~,idx] = sortrows([bin,xord], [1,2]); % Sort by the clusters and the zig-zag
B = A( idx, : ); % Create re-ordered array
绘制这个,看起来就像你想要的
figure(99); clf; hold on;
plot( A(:,1), A(:,2), '-o' );
plot( B(:,1), B(:,2), '-', 'linewidth', 1.5 );
set(gca, 'YDir', 'reverse');
legend( 'Original','Reordered' );
【讨论】:
【参考方案5】:使用nearest neighbor search,您可以在其中定义自定义距离度量,这使得 Y 方向上的距离比 X 方向上的距离更昂贵。然后从左下角开始算法。
Cartesian coordinates 中的“正常”Euclidean distance 由sqrt( (x2 - x1)^2 + (y2 - y1)^2 )
计算得出
要使 y 方向更昂贵,请使用自定义距离公式,将 y
结果乘以一个常数:
sqrt( (x2 - x1)^2 + k*(y2 - y1)^2 )
如果常量k
大于 1 但不会大很多,我会从 2 开始。
【讨论】:
以上是关于对给定模式中的以下坐标进行排序:的主要内容,如果未能解决你的问题,请参考以下文章