相机边缘跟随

Edge following with camera

我想用一个跟随机器人跟随下图中最右边的边缘。

我尝试了简单的 "thresholding",但不幸的是,它包括模糊的白色光晕:

设置阈值的原因是为了从 Sobel 边缘检测器获得干净的线条:

有没有好的算法可以用来沿着这条边隔离 edge/move?我目前使用的那个似乎容易出错,但它是迄今为止我能想到的最好的一个。

注意:边缘可能会向任何方向弯曲或对齐,但边缘上的点总是非常靠近图像的中心。 Here's a video of what I'm trying to do. 由于光晕搞砸了阈值,它在 (1:35) 之后没有正确跟随边缘。


这是另一个示例:

在这里,我填充了最中心的边缘,将其与右下角的小凸起分开:

最简单的方法(竖线)

如果你知道你的图片在线条的右侧会有黑色,这里有一个简单的方法:

1) 应用Sobel算子求x方向的一阶导数。结果将是在梯度最强的地方最负的图像。 (使用较大的内核大小来平均化光晕效果。您甚至可以先对图像应用高斯模糊,如果 7x7 内核不够,则可以获得更多的平均。)

2) 对于图像的每一行,找到最小(即最负)值的索引。那是你对该行中行位置的估计。

3) 随心所欲。 (也许取这些线位置的中值,在图像的上半部分和下半部分,来估计描述该线的 2 个点。)

稍微高级一点(任意行)

如果您不知道直线的方向,但您知道它足够直,您可以用直线来近似它,请使用此方法。

1)

dx = cv2.Sobel(grayscaleImg,cv2.cv.CV_32F,1,0,ksize=7)
dy = cv2.Sobel(grayscaleImg,cv2.cv.CV_32F,0,1,ksize=7)
angle = np.atan2(dy,dx)
magnitudeSquared = np.square(dx)+np.square(dy)

您现在有了图像中每个点的角度(以弧度为单位)和渐变幅度。

2) 从这里您可以使用基本的 numpy 操作来查找直线:过滤点以仅保留 magnitudeSquared > 某个阈值的点。然后获取最常见的角度(np.bincount() 对此很有用)。现在你知道你的线的角度了。

3) 进一步过滤点以仅保留接近该角度的点。您现在拥有线上的所有点。通过这些点的坐标画一条线。

最先进最脆(任意曲线)

如果您真的需要处理曲线,这里有一个方法:

1) 使用您上面的方法对图像进行阈值处理。手动调整阈值,直到 white/black 划分大致发生在您想要的位置。 (可能 127 不是正确的阈值。但如果您的照明条件一致,您可能会找到一个有效的阈值。确认它适用于多个图像。)

2) 使用 OpenCV 的 findcontours() to fit a curve to the white/black boundary. If it's too choppy, use approxPolyDP() 来简化它。