之前做过一个基于深度相机的图像矫正,其中使用深度相机计算了需要矫正的平面图像区域对应的法向量。
本来是直接使用pcl提供的分割接口,但是使用的过程中发现不是很稳定,所以就用pca的方法写了一下。
主要原理:pca的方法计算出了特征值和特征向量。再结合平面点云在法向量方向的差异是最小的,那么特征值最小的特征向量即为法向量,具体原理可以百度其他大佬的博客。
Eigen::Vector3f minVec;//待测平面的法向量
//定义每个表面小块的3x3协方差矩阵的存储对象
Eigen::Matrix3f covariance_matrix;
//定义一个表面小块的质心坐标16字节对齐存储对象
Eigen::Vector4f xyz_centroid;
//估计质心坐标
pcl::compute3DCentroid(*cut, xyz_centroid);
//计算3x3协方差矩阵
pcl::computeCovarianceMatrix(*cut, xyz_centroid, covariance_matrix);
Eigen::EigenSolver<Eigen::Matrix3f> es(covariance_matrix);
Eigen::Matrix3f val = es.pseudoEigenvalueMatrix();
Eigen::Matrix3f vec = es.pseudoEigenvectors();
//cout << "特征值:" << endl << es.eigenvalues() << endl << endl;
cout << "特征值:" << endl << val << endl << endl;
// cout << "特征向量:" << endl << es.eigenvectors() << endl << endl;
cout << "特征向量:" << endl << vec << endl << endl;
int minVal = 0;
if (val(0, 0) > val(1, 1))
{
minVal = 1;
}
if (val(minVal, minVal) > val(2, 2))minVal = 2;
for (int i = 0; i < 3; i++)
{
minVec(i) = vec(i, minVal);
}
cout << "特征值最小为第:" << minVal + 1 << "个" << endl;
cout << "该特征值为" << val(minVal, minVal) << endl;
cout << "该特征向量为" << minVec << endl;