当前情况:我正在尝试从图像中提取片段。多亏了 openCV 的findContours()
方法,我现在有了每个轮廓的 8 个连接点的列表。但是,这些列表不能直接使用,因为它们包含很多重复项。
问题:给定一个包含重复的 8 个连接点的列表,从中提取段。
可能的解决方案:
- 起初,我使用了openCV的
approxPolyDP()
方法。但是,结果非常糟糕......这是缩放的轮廓:
这是结果approxPolyDP()
:(9 段!有些重叠)
但我想要的更像是:
这很糟糕,因为approxPolyDP()
可以在“几个段”中转换“看起来像几个段”的东西。但是,我所拥有的是一个点列表,这些点往往会对其自身进行多次迭代。
例如,如果我的观点是:
0 1 2 3 4 5 6 7 8
9
然后,点列表将是0 1 2 3 4 5 6 7 8 7 6 5 4 3 2 1 9
......如果点数变大(> 100),那么approxPolyDP()
不幸的是提取的段不是重复的(即:它们相互重叠,但不严格相等,所以我可以' t 只是说“删除重复项”,而不是例如像素)
- 也许,我有一个解决方案,但它很长(虽然很有趣)。首先,对于所有 8 连接列表,我创建一个稀疏矩阵(为了提高效率),如果像素属于列表,则将矩阵值设置为 1。然后,我创建了一个图形,其中节点对应于像素,相邻像素之间有边。这也意味着我在像素之间添加了所有缺失的边缘(复杂性很小,可能是因为稀疏矩阵)。然后我删除所有可能的“正方形”(4 个相邻节点),这是可能的,因为我已经在处理非常薄的轮廓。然后我可以启动最小生成树算法。最后,我可以用 openCV 近似树的每个分支
approxPolyDP()
总结一下:我有一个乏味的方法,我还没有实现它,因为它看起来很容易出错。但是,我问你,Stack Overflow 的人:还有其他现有的方法,可能有很好的实现吗?
编辑:澄清一下,一旦我有一棵树,我可以提取“分支”(分支从链接到 3 个或更多其他节点的叶子或节点开始)然后,openCV 中的算法approxPolyDP()
是Ramer–Douglas–Peucker 算法,这里是它所做的维基百科图片:
有了这张图,很容易理解为什么当点可能相互重复时它会失败
另一个编辑:在我的方法中,有一些值得注意的地方。当您考虑位于网格中的点(如像素)时,通常,最小生成树算法没有用,因为有许多可能的最小树
X-X-X-X
|
X-X-X-X
与
X-X-X-X
| | | |
X X X X
但两者都是最小生成树
但是,在我的例子中,我的节点很少形成集群,因为它们应该是轮廓,并且已经有一个细化算法可以预先在findContours()
.
回答 Tomalak 的评论:
如果 DP 算法返回 4 段(从点2
到中心的段有两次)我会很高兴!当然,通过良好的参数,我可以达到“偶然”拥有相同片段的状态,并且可以删除重复片段。但是,很明显,该算法不是为它设计的。
这是一个包含太多细分的真实示例: