计算边线斜率的有效方法
Efficient way of computing slopes of edge lines
我对图像进行了边缘检测(使用 Python 2-7 和 OpenCV 3.2)并得到如下图所示的结果,即一个像素宽的边缘不一定闭合(可以 "loose ends"), 以及可能存在的漏洞:
现在我想得到这些边的"derivative",也就是每个点的"slope",如下图:
目前,我设法做到这一点的唯一方法是非常本地化。对于边缘的每个点(下一张 "zoomed" 图片中的红色),我围绕它创建一个圆(粉红色),用边缘遮住圆以获得红点的邻居,然后计算这两个点的斜率邻居。
但是,如果边缘有孔(它们经常这样做)或靠近其他边缘(它们经常有)并且掩盖所有点的计算量很大,所以我想知道是否有更好的方法。
我的第一个想法是样条插值,但您需要提供一个 有序 点列表作为输入,除非您使用像素,否则您不能为给定的边缘提供该列表邻居跟踪算法,如果边缘不是那么好,也会变得相当混乱。
我也想到了 findContours 但它需要封闭的边缘,否则它会产生一个像素宽边缘的轮廓,即边缘两侧的两条线,从边缘的任意位置开始,简而言之,它是一团糟。
有没有比我的实际方法更简洁、更有效的方法来实现我想要的? OpenCV是否有任何资源或者它的工作是在边缘检测之后完成的(我认为后者更有可能!)?
P.S。 : "I don't think there is a better way" 是我准备接受的答案!
所以,如果我理解正确的话,你需要的是一个没有漏洞的有序列表,因为在那之后你似乎知道如何继续获得你的结果。 因此,您应该集中精力获取有序的无间隙列表。
FindContours 确实输出了一个有序列表,但可能不是您需要的顺序。它以 TOP-DOWN / LEFT-RIGHT 优先级对连接的像素进行分组。因此,它按顺序滑动每一行,当它碰到一个白色像素时,它会找到第一个轮廓。因此,在您的图像中,它找到的第一个轮廓实际上是右侧的轮廓,因为它的 Y 值最接近 0。
对于此特定图像,如果将其旋转 90 度,您会发现它实际上会按照您需要的方式排列轮廓和点。但情况会一直如此吗?只有你知道。如果有一个 pre-process 方法可以应用于您的图像,这将保证 findContours 将以正确的方式对您的像素进行排序,剩下的就很容易了。如果没有,我建议您创建自己的 pixel-connectivity 算法,它将根据您的需要运行,因为您所有的问题都取决于获得有序列表。
获得有序列表后,只需插入缺失的像素即可。
如果您有一组有序的像素,"closing the gaps" 很容易,因为您只需要找到间隙并在它们之间进行插值作为近似值,这可能不会损害您的算法。
我对图像进行了边缘检测(使用 Python 2-7 和 OpenCV 3.2)并得到如下图所示的结果,即一个像素宽的边缘不一定闭合(可以 "loose ends"), 以及可能存在的漏洞:
现在我想得到这些边的"derivative",也就是每个点的"slope",如下图:
目前,我设法做到这一点的唯一方法是非常本地化。对于边缘的每个点(下一张 "zoomed" 图片中的红色),我围绕它创建一个圆(粉红色),用边缘遮住圆以获得红点的邻居,然后计算这两个点的斜率邻居。
但是,如果边缘有孔(它们经常这样做)或靠近其他边缘(它们经常有)并且掩盖所有点的计算量很大,所以我想知道是否有更好的方法。
我的第一个想法是样条插值,但您需要提供一个 有序 点列表作为输入,除非您使用像素,否则您不能为给定的边缘提供该列表邻居跟踪算法,如果边缘不是那么好,也会变得相当混乱。
我也想到了 findContours 但它需要封闭的边缘,否则它会产生一个像素宽边缘的轮廓,即边缘两侧的两条线,从边缘的任意位置开始,简而言之,它是一团糟。
有没有比我的实际方法更简洁、更有效的方法来实现我想要的? OpenCV是否有任何资源或者它的工作是在边缘检测之后完成的(我认为后者更有可能!)?
P.S。 : "I don't think there is a better way" 是我准备接受的答案!
所以,如果我理解正确的话,你需要的是一个没有漏洞的有序列表,因为在那之后你似乎知道如何继续获得你的结果。 因此,您应该集中精力获取有序的无间隙列表。
FindContours 确实输出了一个有序列表,但可能不是您需要的顺序。它以 TOP-DOWN / LEFT-RIGHT 优先级对连接的像素进行分组。因此,它按顺序滑动每一行,当它碰到一个白色像素时,它会找到第一个轮廓。因此,在您的图像中,它找到的第一个轮廓实际上是右侧的轮廓,因为它的 Y 值最接近 0。
对于此特定图像,如果将其旋转 90 度,您会发现它实际上会按照您需要的方式排列轮廓和点。但情况会一直如此吗?只有你知道。如果有一个 pre-process 方法可以应用于您的图像,这将保证 findContours 将以正确的方式对您的像素进行排序,剩下的就很容易了。如果没有,我建议您创建自己的 pixel-connectivity 算法,它将根据您的需要运行,因为您所有的问题都取决于获得有序列表。
获得有序列表后,只需插入缺失的像素即可。
如果您有一组有序的像素,"closing the gaps" 很容易,因为您只需要找到间隙并在它们之间进行插值作为近似值,这可能不会损害您的算法。