通过大点云拟合线

数据挖掘 机器学习 聚类 回归
2021-10-12 12:21:48

我有一大组点(大约 10k 点)由粒子轨迹(在 xy 平面上的移动由相机拍摄,因此在我的示例集中为 3d - 256x256px 和 ca 3k 帧)和噪声。这些粒子在大致直线上大致(但只是大致)沿相同方向行进,因此为了分析它们的轨迹,我试图通过这些点拟合线。我尝试使用 Sequential RANSAC,但找不到可靠地挑选出误报以及 T-和 J-Linkage 的标准,它们太慢且不够可靠。

这是我使用顺序 Ransac 获得的数据集的一部分图像,具有良好和不良拟合:在此处输入图像描述 我在这里使用粒子斑点的质心,斑点大小在 1 到大约 20 像素之间变化。

我发现例如仅使用每 10 帧的子样本也工作得很好,因此可以通过这种方式减少要处理的数据大小。

我读了一篇关于神经网络可以完成的所有事情的博客文章,并想在我开始阅读之前问你这是否是一个可行的应用程序(我来自非数学背景,所以我必须做一点阅读)?

或者你能建议一种不同的方法吗?

谢谢!

附录:这是 Matlab 函数的代码,用于生成包含 30 条平行噪声线的样本点云,我还无法区分:

function coords = generateSampleData()
coords = [];
for i = 1:30
    randOffset = i*2;
    coords = vertcat(coords, makeLine([100+randOffset 100 100], [200+randOffset 200 200], 150, 0.2));
end

figure
scatter3(coords(:,1),coords(:,2),coords(:,3),'.')

function linepts = makeLine(startpt, endpt, numpts, noiseOffset)
    dirvec = endpt - startpt;
    linepts = bsxfun( @plus, startpt, rand(numpts,1)*dirvec); % random points on line
    linepts = linepts + noiseOffset*randn(numpts,3); % add random offsets to points
end

end
2个回答

根据反馈并试图找到更有效的方法,我使用专用距离测量开发了以下算法。

执行以下步骤:

1)定义一个距离度量返回:

- 如果点不属于一条线

点的欧几里得距离- 如果点根据定义的参数构成一条线,即

  • 它们的距离大于或等于min_line_length并且

  • 它们的距离小于或等于max_line_length并且

  • 该线 由至少min_line_points个点组成,其距离低于line_width/2

2)使用此距离度量计算距离矩阵(使用数据样本用于大型数据集;相应地调整线参数)

3) 找到距离最大的点 A 和 B - 如果距离为零,则转至步骤 5)

请注意,如果距离大于零,则点 A 和 B 正在根据我们的定义构建一条线

4)获取属于线AB的所有点并将它们从距离矩阵中删除。重复步骤 3) 找到另一行

5) 用选定的线检查点的覆盖范围,如果仍有大量点未被覆盖,则使用调整的线参数重复整个算法。

6) 如果使用了数据样本 - 将所有点重新分配给线并重新计算边界点。

使用以下参数:

线宽- line_width/2 是该点与理想线的允许距离 = r line_width

最小线长 - 距离较短的点不被认为属于同一条线 = r min_line_length

最大线长 - 距离较长的点不被认为属于同一条线 = r max_line_length

一条线上的最小点- 点较少的线被忽略 =r min_line_points

使用您的数据(在对参数进行一些摆弄之后),我得到了涵盖所有 30 行的良好结果。

在此处输入图像描述

更多细节可以在knitr 脚本中找到

我用蛮力方法解决了类似但更简单的任务。简化是假设该线是线性函数(在我的情况下,甚至系数和截距都在某个已知范围内)。

因此,这通常不会解决您的问题,其中一个粒子可以与轴 x 正交移动(即它不跟踪任何功能),但我将解决方案作为可能的灵感发布。

1)取A和B两点的所有组合,A(x)> B(x)+常数(避免计算系数时的对称性和高误差)

2) 计算线AB的系数c和截距i

 A(y) = i + c * A(x)
 B(y) = i + c * B(x)
 A(y) - B(y) = c * (A(x) - B(x))
 c = (A(y) - B(y)) / (A(x) - B(x))
 i = A(y) - c * A(x)

3)四舍五入系数和截距(这应该消除/降低由网格中的点引起的错误问题)

4) 对于每个截距和系数,计算这条线上的点数

5) 只考虑点高于某个阈值的线。

简单的例子见这里