如何使用Python检测重叠或近似重复的SVG路径并实现去重
SVG近似重复路径检测去重方案
问题原因
你遇到的AssertionError是svgpathtools的intersect方法的已知限制:该方法不支持处理完全重合的线段,遇到这种情况会直接抛出断言错误,因此通过计算交点判断重复的思路不可行。
实现思路
近似重复路径的核心判断依据是几何特征相似度,而非直接对比d属性字符串(d属性会因为导出时的写法差异、精度截断、路径方向不同出现内容不一致但几何形状完全重合的情况),可以通过三个维度的特征对比实现检测:
- 路径总长度差值
- 路径包围盒(最小外接矩形)差值
- 路径均匀采样点的平均距离差值
完整实现代码
from svgpathtools import svg2paths, wsvg import sys def is_path_approx_equal(p1, p2, tol=0.01, sample_count=50): # 先对比总长度,差异超过容差直接返回不相等 len_diff = abs(p1.length() - p2.length()) if len_diff > tol: return False # 再对比包围盒 bbox1 = p1.bbox() bbox2 = p2.bbox() bbox_diff = sum([abs(a - b) for a, b in zip(bbox1, bbox2)]) if bbox_diff > tol * 4: return False # 最后采样点对比,同时考虑路径方向相反的情况 sample_points1 = [p1.point(i / sample_count) for i in range(sample_count + 1)] sample_points2_normal = [p2.point(i / sample_count) for i in range(sample_count + 1)] sample_points2_reverse = [p2.point(1 - i / sample_count) for i in range(sample_count + 1)] # 计算两个方向的平均距离 dist_normal = sum(abs(p1 - p2) for p1, p2 in zip(sample_points1, sample_points2_normal)) / (sample_count + 1) dist_reverse = sum(abs(p1 - p2) for p1, p2 in zip(sample_points1, sample_points2_reverse)) / (sample_count + 1) min_dist = min(dist_normal, dist_reverse) return min_dist < tol if __name__ == "__main__": svg_file = sys.argv[1] output_file = "deduplicated_" + svg_file paths, attrs = svg2paths(svg_file) unique_paths = [] unique_attrs = [] for path, attr in zip(paths, attrs): # 检查当前路径是否和已保留的路径重复 is_dup = False for kept_path in unique_paths: if is_path_approx_equal(path, kept_path): is_dup = True break if not is_dup: unique_paths.append(path) unique_attrs.append(attr) # 导出去重后的SVG wsvg(unique_paths, attributes=unique_attrs, filename=output_file) print(f"去重完成,原路径数:{len(paths)},保留路径数:{len(unique_paths)},输出文件:{output_file}")
参数调整说明
tol:容差值,单位和SVG绘图单位一致,CAD导出的图纸一般设置为0.01~0.1即可,形状误差大可以适当调大sample_count:采样点数量,形状越复杂可以设得越高,一般20~100就能满足需求
额外注意项
如果你的SVG中路径样式(填充、描边、宽度)不一致,也可以在对比逻辑中加入样式属性的判断,避免把形状重合但样式不同的路径误判为重复。
内容的提问来源于stack exchange,提问作者simone
相关产品推荐
相关产品推荐

