記事ディレクトリ
0 まえがき
点群モデリングのプロセスでは、スキャンされた点群を校正する必要がある場合があります。実際の使用では、多くの場合、地面が基準面として使用され、スキャンされた 3D 空間点群をその面に当てはめて補正する必要があります。スキャン結果。この論文は、三次元空間離散点フィッティング平面アルゴリズムを要約し、いくつかのプログラミング言語でのアルゴリズム実装コードを示します。
1. アルゴリズム原理
(1) 最小二乗法
(2) 平面方程式フィッティング
2. アルゴリズムの実装
(1)C#
using MathNet.Numerics.LinearAlgebra;
using MathNet.Numerics.LinearAlgebra.Double;
List<List<double>> dLL =new List<List<double>>();
using (StreamReader sr = new StreamReader("E:\\4.txt", Encoding.UTF8))
{
string line;
// 从文件读取并显示行,直到文件的末尾
while ((line = sr.ReadLine()) != null)
{
string[] strs = line.Split(',');
List<double> dL = new List<double>();
dL.Add(double.Parse(strs[0]));
dL.Add(double.Parse(strs[1]));
dL.Add(double.Parse(strs[2]));
dLL.Add(dL);
}
}
Matrix<double> A,b;
double[,] dA=new double[dLL.Count(), 3];
double[,] db = new double[dLL.Count(), 1];
double[,] da = new double[3, 1];
for (int i = 0; i < dLL.Count(); i++)
{
dA[i, 0] = dLL[i][0];
dA[i, 1] = dLL[i][1];
dA[i, 2] = 1;
db[i,0] = dLL[i][2];
}
A = DenseMatrix.OfArray(dA);
b = DenseMatrix.OfArray(db);
Matrix<double> a = (A.Transpose() * A).Inverse() * A.Transpose() * b;
Console.WriteLine("a0,a1,a2:"+a[0,0].ToString("f6")+","+a[1,0].ToString("f6") + ","+a[2,0].ToString("f6"));
(2)C++
//planePoints存储需要拟合的三维点云
vector<Eigen::Vector3d> planePoints;
Eigen::MatrixXd A(planePoints.size(), 3);
Eigen::VectorXd b(planePoints.size());
//将观测点输入矩阵
for (int i = 0; i < planePoints.size(); i++)
{
A(i, 0) = planePoints[i](0);
A(i, 1) = planePoints[i](1);
A(i, 2) = 1;
b(i) = planePoints[i](2);
}
//使用最小二乘法求得系数向量
Eigen::Vector3d a = (A.transpose()*A).inverse()*A.transpose()*b;
(3)マットラボ
%文件名
fileName = "E:\\4.txt";
points = csvread(fileName , 0, 0);
length = size(points(:,1));
A=[points(:,1),points(:,2),ones(length(1),1)];
b=points(:,3);
a=inv(A'*A)*A'*b;
(4)ジャワ
//s为点文件数据字符串
String[] strs = s.toString().split("\n");
double dA[][] = new double[strs.length][3];
double db[][] = new double[strs.length][1];
double da[][] = new double[3][1];
for(int i = 0;i <strs.length;i++){
if(strs[i].equals(""))continue;
String[] strs2 = strs[i].split(",");
dA[i][0]=Double.parseDouble(strs2[0]);
dA[i][1]=Double.parseDouble(strs2[1]);
dA[i][2] = 1;
db[i][0]=Double.parseDouble(strs2[2]);
}
//multiply、inverse、transpose分别为矩阵乘法、求逆、转置
da = multiply(multiply(inverse(multiply(transpose(dA),dA)),transpose(dA)),db);
(5)VBA
Imports MathNet.Numerics.LinearAlgebra
Imports MathNet.Numerics.LinearAlgebra.Double
Dim arr() As String, i As Long
arr = Split(CreateObject("scripting.filesystemobject").opentextfile("E:\\4.txt").readall.ToString(), vbLf)
Dim dA(UBound(arr), 2) As Double, db(UBound(arr), 0) As Double
Dim str() As String
For i = 0 To UBound(arr)
'ReDim Preserve Txt(i)
If arr(i) = "" Then
Continue For
End If
str = Split(arr(i), ",")
dA(i, 0) = Convert.ToDouble(str(0))
dA(i, 1) = Convert.ToDouble(str(1))
dA(i, 2) = 1
db(i, 0) = Convert.ToDouble(str(2))
Next
Dim A, b, ma As Matrix
A = DenseMatrix.OfArray(dA)
b = DenseMatrix.OfArray(db)
ma = (A.Transpose() * A).Inverse() * A.Transpose() * b
Console.WriteLine("a0,a1,a2:" + ma(0, 0).ToString("f6") + "," + ma(1, 0).ToString("f6") + "," + ma(2, 0).ToString("f6"))
(6)パイソン
from numpy import *;
f=open('E:\\4.txt', encoding='gbk')
txt=[]
strs = []
A = []
b = []
a = []
for line in f:
strs=line.strip().split(',')
A.append([float(strs[0]),float(strs[1]),1])
b.append([float(strs[2])])
A = mat(A)
b = mat(b)
a = (A.T*A).I*A.T*b
print(a)
参考資料:
[1] HIIWAR_ZB.最小二乗法 - 平面方程式のフィッティング (深度カメラの外部パラメータ校正、地面校正) ; 2020-06-23 [アクセス日 2023-06-25].
[2] Haha kls. Minimum two Multiplication Fitting plan ; 2018-09-10 [accessed 2023-06-25].
[3] コートを脱いで本質を見る3次元空間離散点平面フィッティングアルゴリズム C++実装; 2019-03-07 [accessed 2023-06] -25]。