【问题标题】:Separate L shape into two lines将L形分成两条线
【发布时间】:2015-11-13 06:18:24
【问题描述】:

我希望检测与标记的距离和方向。标记为L形;两条等宽等高的线连成一个L形。

为了检测方向和距离,我需要将相机捕捉到的 L 形分解为两条线。

考虑到代码需要每帧运行多次,什么是轻量级的方法?

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

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

下图展示了相机如何捕捉到 L 形的不同结果。

我在想我可以通过用一条穿过边界框的质心和中心的线来分割 L 形,但那行不通。

关于我认为如何完成的粗略头脑风暴草图:

【问题讨论】:

  • 你能用PNG重新发布相同的图像吗?我正在尝试使用您的示例图像来回答我的问题,但 JPEG 压缩会丢失一些信息,因此很难轻松进行正确的分割 =(
  • 好的,马上来!
  • 上一张图片现在替换为 PNG。
  • 谢谢!好多了 =) 一个答案,来了!
  • 很好奇你的方法是什么:) 我已经考虑了好几天了!

标签: opencv image-processing computer-vision


【解决方案1】:

扫描线!

在 Python 中查看(更新的)演练 here,其中包含用于可视化我的数据之旅的图像 :)

“扫描线”解决方案跳到最后


扫描线

基础知识

假设

我从您的示例图像中假设这些约束

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

标记您的二进制图像

您首先想知道哪些像素是哪个 L 的一部分,这是通过“标记”二值图像来完成的。

还计算每个体积的边界框,如下所示:

旋转坐标系

现在真正的诀窍是从 x/y 正交系统变为每个形状的“L 形参考”。

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

让我们考虑一下 PCA 方式

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

我不会深入探讨,但您可以查看此intro to PCA 帖子以感受它。

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

但这会浪费计算能力,因为与通常的 PCA 情况相比,您的 L 点位置已经受到限制(它们在一条线上,而不是随机分散的)。这个问题涉及的线性代数野兽在这个小问题上是矫枉过正

霍夫线,救援!

您只想在 2D 图像中找到线条? 对线使用霍夫变换(也称为“霍夫线”)。 OpenCV 有。

又是一个不错的介绍:OpenCV's python tutorial on Hough Lines

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


新希望

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

RANSAC

我曾想过在您的数据上使用 RANSAC 变体:毕竟,您希望将线拟合到点云中。 基本技术是你可能知道的总结

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

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

但我看到了并发症:

  • 哪个模型?:你是用 4 个点来定义 2 条线,还是用 2 个点来定义一条线,然后做两次?
  • 没有异常值:你并没有真正的异常值,那么为什么要在这样一个微不足道的问题上使用 RANSAC 呢?
  • 计算能力:你真的会无缘无故地迭代数千次,因为你是在随机查看你的点。

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

扫描线!

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

如果我们在Y=0 处水平切片,我们将得到一个一维数组,其连续区域定义为True

那么如果我们像这样每隔一段时间对图像进行切片以定义 L 的向量呢?

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

我们现在有 2 个 2D 点定义通过您的图像的第一条线。

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

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

再一次,如果现在有点难以想象,请看我的code walkthrough的结尾部分

【讨论】:

  • 虽然我考虑过霍夫变换,但我认为有一种更快更准确的方法可能。鉴于代码需要运行每一帧(在低端设备上),尽可能快的计算很重要。另外,由于我进行三角测量,因此我需要最大的精度。正如您的解决方案所示,采样率需要较低才能进行快速处理。
  • 确实如此。我记得有一篇论文避免使用差异来估计方向,在那里看到它:vsi.cs.uni-frankfurt.de/download/EUSIPCO2000.pdf 请注意,由于性能限制,你的问题变得很深奥! (研究论文等)
  • 查看我更新的解决方案,使用扫描线派生技术。我居然半夜醒来把这个想法写下来^^
  • 巧合的是,昨天晚上我也有类似的想法 :) 我认为这与您的方法很接近,但要快一些。我还在努力,如果不成功,我一定会试试你的方法。
  • 你知道他们怎么说伟大的思想...... ;) 你是对的,虽然我的方法需要做大量的优化。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-11-10
  • 1970-01-01
相关资源
最近更新 更多