如何在二值图像中检测曲线?

17

我有一张二进制图片,想要检测/跟踪其中的曲线。我不知道任何信息(坐标、角度等)。有没有人能指导我应该如何开始?假设我有这张图片 enter image description here

我想将曲线与其他直线分离开来。我只对曲线及其参数感兴趣。我想将曲线的信息(在数组中)存储起来以便以后使用。


https://dev59.com/U1XTa4cB1Zd3GeqP4sTQ - carlosdc
5个回答

16

这真的取决于你所谓的“曲线”是什么意思。

如果您只想将每个离散像素集合标识为“曲线”,则可以使用连通组件算法。每个组件将对应一个像素集合。然后,您可以应用一些测试来确定组件的直线性或其他特征。

如果您正在寻找直线、圆形曲线或任何其他参数曲线,则可以使用霍夫变换来从图像中检测这些元素。

最好的方法真的要取决于您要寻找哪些曲线以及您需要了解哪些关于曲线的信息。

参考链接:


1
示例图中给出了曲线的示例,可以说是圆形曲线。所需信息包括表示(或绘制)曲线所必需的所有相关内容,我想将它们存储。我已经尝试了很多次,但无法做到这一点。如果可能的话,请通过一些伪代码或任何与我的问题更接近的链接来帮助我。谢谢。 - Developer
1
考虑使用循环霍夫变换,以原点和半径作为参数。一旦定位了圆曲线,您可以提取适当的角度范围。有关更多链接,请参阅答案。 - John Percival Hackworth
@JohnPercivalHackworth 假设我已经找到了img_ori的边缘,然后将其转换为二进制图像img_bin,然后使用连通组件算法获取像素的集合。对于每个集合,是否有一种方法可以从img_ori扫描邻近像素并找到暗色和亮色像素,并将它们的位置存储到暗色和亮色组中? - June Wang

2

由于您似乎已经有一个好的二进制图像,最简单的方法可能是分离图像的不同连通部分,然后计算它们的参数。

首先,您可以通过扫描图像进行分离,并在遇到黑色像素时应用标准的洪水填充算法以查找形状中的所有像素。 如果您使用Matlab图像工具箱,则可以使用bwconncompbwselect过程来执行此操作。 如果您的形状不是完全连接的,则可以对图像应用形态学闭合操作以连接形状。

分割出不同的形状后,您可以通过测试其偏离直线的程度来过滤曲线。您可以简单地选择曲线的端点,并计算其他点距离由端点定义的直线多远。如果这个值超过了某个最大值,则说明您有一条曲线而不是一条直线。
另一种方法是测量端点之间的距离与对象长度之比。对于直线,这个比值会接近1,而对于曲线和波浪形状,这个比值会更大。
如果您希望将角度与曲线分开处理,可以检查曲线的方向梯度。对形状进行分割,选择一组等距点并为每个点计算与前一个点和下一个点的角度。如果角度差太大,则说明您没有得到平滑的曲线,而是某种有角度的形状。
实现中可能存在的困难包括厚线条,可以通过骨架转换解决。有关matlab骨架和查找曲线端点的实现,请参见 matlab图像处理工具包文档

在分割出不同的形状之后,如何扫描原始图像(非二进制)中特定形状的相邻像素? - June Wang

1

使用链码也可以提供另一种解决方案。 理解OCR中的Freeman链码

链码基本上为每个像素分配一个值,介于1-8(或0到7)之间,表示你的连接前身在8连通邻域中的哪个像素位置。因此,就像Hackworth建议的那样,首先执行连接组件标记,然后为每个组件曲线计算链码。查看链码的分布和梯度,可以轻松区分直线和曲线。但是,该方法的问题在于当我们有振荡曲线时,梯度不太有用,因此需要依靠链码的聚类!


1

1)阅读一本关于图像分析的书籍。

2)扫描黑色像素,找到后查找相邻的黑色像素,存储它们的位置,然后将它们变为白色。这样可以得到一个对象的点并从图像中删除它。只需重复此过程,直到没有剩余的黑色像素为止。

如果您想将曲线与直线分开,请尝试进行线拟合,然后获取相关系数。类似的算法也适用于曲线,相关性告诉您该点与理想形状的接近程度。


你如何找到相邻的像素? - June Wang

-1

虽然我不是计算机视觉专家,但我认为你可以使用一些基本的边缘检测算法(例如Sobel滤波器)相对容易地在二进制图像中检测出线条/曲线。


8
由于投票反对您的人没有留下解释:边缘检测算法(例如Sobel滤波器)实际上并不“检测”边缘,它只是“增强”具有大变化(边缘)的区域,并“减弱”低变化的区域。然后,您可以通过应用某种阈值来“提取”边缘。结果将是一个二进制图像。 - bjoernz

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接