【问题标题】:Efficient way of computing slopes of edge lines计算边缘线斜率的有效方法
【发布时间】:2017-06-01 09:48:39
【问题描述】:

我对图像进行了边缘检测(使用 Python 2-7 和 OpenCV 3.2),结果如下图所示,即一个像素宽的边缘不一定是闭合的(可能有“松散的末端”),并且可能有孔:

现在我想得到这些边的“导数”,即每个点的“斜率”,如下图所示:

目前,我设法做到这一点的唯一方法是非常本地化。对于边缘的每个点(下一张“放大”图片中的红色),我在它周围创建一个圆圈(粉红色),用边缘掩盖圆圈以获得红色点的邻居,然后计算这两个邻居的斜率。

但是,如果边缘有孔(它们经常这样做)或靠近其他边缘(它们经常存在)并且屏蔽所有点的计算量很大,那么它可能会非常混乱,所以我想知道是否有更好的方式。

我的第一个想法是样条插值,但您需要提供一个 有序 点列表作为输入,除非您使用可以如果边缘不太好,也会变得非常混乱。
我也想到了 findContours 但它需要封闭的边缘,否则它会产生一个像素宽的边缘的轮廓,即边缘两侧的两条线,从边缘的任意位置开始,简而言之就是一团糟。

有没有比我的实际方法更清洁、更有效的方法来实现我想要的? OpenCV 是否有任何资源,或者它的工作是在边缘检测之后完成的(我认为后者更有可能!)?

附: :“我认为没有更好的方法”是我准备接受的答案!

【问题讨论】:

  • 最简单的方法是将您的对象表示为轮廓,但正如您所说,您的对象可能有孔并且可能很难将其表示为“连接”轮廓。
  • 感谢您的回复。即使没有孔,我的对象也不一定是封闭的,它们大多是松散的边缘。因此 findContours() 没有帮助。我编辑了我的问题以考虑到这一点。
  • 您仍然可以通过“轮廓”(沿曲线的点位置的有序列表)来表示您的曲线段,但您必须以不同的方式计算它们(而不是 findContours)。在那之后,计算斜率变得简单,并且可能总体上更有效。但是仍然存在将边缘分组为曲线段的问题......
  • 是的,对于这个“将边缘分组为曲线”步骤,除了计算每个像素的相邻像素数量以找到极端,然后迭代地找到以下邻居......一种算法可能计算效率不高,并且当连接有点困难时容易出错
  • 这是什么意思? “现在我想获得这些边的“导数”,即每个点的“斜率”,如下图所示”。每个点的斜率?线的每个“段”最多有一个斜率。

标签: python-2.7 opencv edge-detection derivative corner-detection


【解决方案1】:

所以,如果我对所有内容的理解都正确,那么您需要的是一个没有漏洞的点的有序列表,因为之后您似乎知道如何继续获得结果。 因此,您应该集中精力获得有序的无间隙列表。

FindContours 确实会输出一个有序列表,但可能不是您需要的顺序。它以自上而下/左至右优先级对连接的像素进行分组。因此,它按顺序滑动每一行,当它碰到一个白色像素时,它会找到第一个轮廓。因此,在您的图像中,它找到的第一个轮廓实际上是右边的轮廓,因为它的 Y 值最接近 0。

对于这个特定的图像,如果将其旋转 90 度,您会发现它实际上会按照您需要的方式排列轮廓和点。但这会一直如此吗?只有你能说出来。如果有一种预处理方法可以应用于您的图像,以保证 findContours 将以正确的方式对您的像素进行排序,那么剩下的就很容易了。如果没有,我建议您创建自己的像素连接算法,该算法将根据您的需要工作,因为您的所有问题都取决于获取有序列表。

获得有序列表后,只需插入缺失的像素。

如果您有一组有序的像素,“缩小间隙”很容易,因为您只需要找到间隙并在它们之间插入一个近似值,这可能不会损害您的算法。

【讨论】:

  • 我认为您是对的,尽管正如我在(已编辑)问题中所说,在 1 像素宽的非闭合线上的 findContour 真的很难看。而且我的图像不会总是这样......但我更好地了解现在的问题,以及我能做什么和不能做什么!
  • 好。作为旁注,我使用 findContours 来描述 1 像素宽的线条并且没有遇到任何问题,我实际上是在使用它来计算对象的尺寸。所以我不知道那里可能有什么问题。很高兴我能帮上忙,干杯。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-05-02
  • 1970-01-01
  • 2017-03-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-09-05
相关资源
最近更新 更多