将L形分成两条线

时间:2015-11-10 14:08:19

标签: opencv image-processing computer-vision

我希望从标记中检测距离和方向。标记是L形;两条宽度和高度相等的线连接成L形。

为了检测方向和距离,我需要将相机上的L形切割成两行。

如果代码需要每帧运行多次,那么执行此操作的轻量级方法是什么?

我已经使用此处描述的算法实现了blob检测:http://www.labbookpages.co.uk/software/imgProc/blobDetection.html

我考虑过使用Hough变换,但我担心每帧执行需要很多处理能力。最重要的是,我认为这不是这种情况下最准确的方法。我已经进行了适当的分析,从单行提取精确的矢量,但不确定如何将L形切割成两行。

下面是相机如何捕捉L形的不同结果的图片。

Example

我以为我可以将L形分割成一条穿过质心和边界框中心的直线来分割L形状,但这并没有成功。

一个粗略的头脑风暴草图,我认为它可能会如何完成:

Rough sketch

1 个答案:

答案 0 :(得分:3)

Scanlines!

请参阅Python中的(更新的)演练here ,其中的图片可视化我的数据之旅:))

跳过" Scanlines"溶液

Lines Vectors

Scanlines的

基本

假设

我假设您的样本图像存在这些约束

  • 您的图像中有(多个)L形。
  • 您可以轻松地对它们进行分割(没有重叠的形状,没有一个L延续到另一个......)
  • 您知道Ls中行线的确切宽度

标记二进制图像

你想先知道哪些像素是L的一部分,这是由"标记"二进制图像。

计算每个卷的边界框,如下所示:

旋转坐标系

现在真正的诀窍是从x / y正交系统转变为" L形指示"对于每个形状。

将其视为将X轴重新定义为L的一个分支,将Y轴重新定义为另一个分支。 一旦我们计算了一个到另一个的转换向量,我们就安全了!

让我们考虑PCA方式

我们现在面临的问题("估计数据集中最大的变化轴")是可以使用协方差的特征向量的时刻。

我不太深入了解它,但你可以看一下这篇intro to PCA帖子来了解它。

问题通常定义在更高维度("给定50维数据集,计算其中的10个最大变异轴"),但可以通过考虑扩展到2D点云问题每个形状单独说明属于L的每个像素都是2D空间中的一个点。

然而,这会浪费计算能力,因为与PCA的通常情况相比,你已经对你的L点位置有限制(他们在线上,而不是随机分散)。这个问题所涉及的线性代数的野兽对这个小问题来说太过分了

Hough Lines,救援!

您只想在2D图像中找到线条? 对线使用Hough变换(也称为" hough lines")。 OpenCV有它。

再一次很好的介绍:OpenCV's python tutorial on Hough Lines

我使用了二进制图像的骨架(这样每条线只投了一次),然后手动选择我给OpenCV算法的参数。 这就是线条有时似乎与特定图像完全匹配的原因,因为采样率等等因此=)

新希望

在你指出了对计算速度的需求之后,我想到了更多使用图像属性的技术。

RANSAC

我想过对您的数据使用RANSAC变体:毕竟,您希望将线条放入点云中。 基本技术就像你可能已经用

总结的那样
  • (随机)选择足够的数据以适合模型(在您的情况下为行)
  • 评估异常值的数量(模型不起作用的数据点)
  • 重申并记录得分最高的模型(并继续这么做一段时间,涉及数学)

RANSAC的一个很好的介绍是this song(奇怪的是)

但我看到了并发症:

  • 哪种型号?:你用4个点来定义2行,或者你为一行做2分并做两次?
  • 没有异常值:你真的没有适当的异常值,那么为什么要使用RANSAC呢?
  • 计算能力:您可能无缘无故地进行数千次迭代,因为您需要随机查看积分。

毋庸置疑,RANSAC无法做到这一点,但我们可以将其作为灵感来源

Scanlines!

让我们考虑你的Ls'边界框。

如果我们在Y=0水平切片,我们将有一个1D数组,其连续区域定义为True

那么如果我们每隔一段时间切开这样的图像来定义L的向量呢?

设置5百分位数作为基线,我们只找到"哪个X-index是Y = 0值的一维数组的中心",然后执行相同的Y = 0.05 * img_width

我们现在有2个2D点定义图像的第一行。

在另一边重复,你有解决方案!

计算上,你只是在img_width长度数组中找到4个中位数, 每个都是你图像中连续的一块内存(Heeeeelllo L2-cache hits!)。

同样,如果现在有点难以想象,请参阅我的code walkthrough

的结尾部分