【发布时间】:2021-06-18 23:10:34
【问题描述】:
你好,
我正在尝试将一堆碰撞在一起的线条组合在一起。例如,如果 A 线与 B 线相撞,B 线与 C 线相撞,但 A 线不会与 C 线相撞。我希望它们都在一起。
我尝试利用集合的属性,所以我只有一个独特的解决方案并避免重复。我也试着让它有点快。我拥有的行数据是浮点数列表:[x1, y1, x2, y2]。
all_lines = lines.tolist()
lines_combinations = list()
for l in all_lines:
#Find if the potential line already belongs to a group in line_combination
remove_list_l = False #is line (l) in a group in lines_combination
remove_list_ol = False #is other line (ol) in a group in lines_combination
line_group = False;
for j in lines_combinations: #Iterate through all combination found already
if tuple(l) in j:
line_group = j
remove_list_l = True
if not line_group:
line_group = {tuple(l)}
#Remove a from the total line list
all_lines.remove(l)
#Iterate through all potential lines
for ol in all_lines:
if check_collision(l, ol, px):
#If collision, check if k is in another group
for k in lines_combinations:
if tuple(ol) in k:
#If true, append both groups together
line_group.union(k)
replace_list_ol = True
if not replace_list_ol:
line_group.add(tuple(ol))
#Remove both groups and add the new joint one
if remove_list_l:
lines_combinations.remove(j)
if replace_list_ol:
if j != k:
lines_combinations.remove(k)
lines_combinations.append(line_group)
算法无法将所有白线和所有棕色线明显相交时合并在一起(白色下面还有一些粉线也应该属于该组)。我不知道这是否是因为我在不同的组中复制了该行,或者算法是否在其他地方失败。最终,我希望任何一行在一个独特的组中出现一次,这样我就可以避免重复。我看不出算法哪里出错了……
我很乐意就如何做到这一点提供建议并使其更快!非常感谢!
编辑:大家好,我能够通过将“line_group.union(k)”行替换为“line_group = line_group.union(k)”来解决我的问题。所以它有效!
但是,每张图片的处理时间约为 30 秒……这需要太多时间。我正在寻找可能的优化建议!
编辑 2:您可以在此处找到我正在训练我的算法的数据: lines.txt 我已将其导出为 pd.DataFrame,因此您可以轻松加载它!我还添加了用于查找交叉点的 check_collision.py 脚本。与此处 M Oehm 的答案非常相似:stack-overflow。但是由于共线性的编辑。
事实证明我的碰撞脚本或排序算法都有问题,因为我将不应该属于一起的组绘制在一起。
【问题讨论】:
-
我觉得
lines_combination应该是一个集合,而不是一个列表,因此查找和删除是 O(1)。您可能还应该对空间进行分区,以便仅检查附近的线的碰撞。 -
我试过了,因为这似乎是最好的方法。但是,似乎我无法在 Python 中创建一组集合。执行 list_combination.add(line_group) 时出现错误:“TypeError: unhashable type: 'set'”。
-
30s的运行时间在不知道问题大小的情况下是没有用的。一张图片通常有多少行?您有可以分享的示例数据集吗?
-
视图片而定。这里是 2500 行。我计划做的第一件事是做矩阵计算。使用数组一次性测试一条线与所有其他线,因此我不必执行 ~ 2500 * 2500 循环。我想知道是否有办法同时测试几行与几行。
-
嗯,我已经写了一个答案:使用扫描线,这很容易实现。如果您需要更快,请使用更高效的 Bentley-Ottmann。如果还不够,请使用带有 BO 算法的图形库。 (具有 2500 条线的扫描线应该足够快,尤其是因为您的大部分线都很短。)如果您愿意,可以使用结果来填充 SIMD 矩阵。