扫描线!
在 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的结尾部分