3d视觉——3.平面提取方式(open3d/python/cpp)

3d视觉——3.平面提取方式(open3d/python/cpp) 这里记录了常用的平面提取方式主要介绍平面在3d点云中的价值和意义以及常用平面提取的场景和方式主要包括最常ranscan算法和最小二乘算法并附上了python/cpp代码的实现方式。场景和问题在点云处理过程中存在大量的平面结构如地面、墙面这些平面可以作为基本特征使用又比如工件的外表可以作为测量的基本元素。所以需要有提取平面的方式获取点云平面。常用算法常用的方式为ranscan法向量过滤最小二乘。ranscan是最常用的平面提取算法法向量过滤最小二乘是更精确的平面提取算法。ranscanranscan算法即随机采样一致性算法是一种迭代算法用于从点云中提取平面。算法原理这个算法的泛用性很强可以用于提取任意形状的几何特征而不仅仅是平面这里根据其应用场景只讨论简化的平面提取原理。1.模型假设平面方程axbyczd02.随机采样点云中不共面3d点这三个点可以确定一个平面解出平面参数a,b,c,d。3.计算点云中所有点到该平面的距离设置阈值距离小于阈值的点为平面点距离大于阈值的点为非平面点。4.统计平面内的点数5.多次重复步骤2-4每次随机采样3d点计算距离统计平面内的点数选取点数最多的平面作为最终结果。这个算法有一个特点就是只要迭代次数多就可以稳定的得到算法特点这个算法是平面提取中最常用的一种使用一个基本的假设即平面内的点数最多平面外的点数最少只要迭代次数多所以可以稳定得到平面。这带来了一个优点就是鲁棒性强在复杂场景中只要有平面基本都能获得。但是也带来了一个缺点就是这个算法含有随机性每次得到的平面都会有轻微不同只能是大致的一个平面。代码实现# ranscan平面提取plane_model,inliersdown_pcd.segment_plane(distance_threshold10,ransac_n3,num_iterations1000)[a,b,c,d]plane_modelprint(f平面模型:{a:.2f}x {b:.2f}y {c:.2f}z {d:.2f} 0)inlier_clouddown_pcd.select_by_index(inliers)o3d.io.write_point_cloud(pointcloud_plane.pcd,inlier_cloud)print(点云保存到pointcloud_plane.pcd)其中distance_threshold点到平面的最大距离内点判定阈值ransac_n为每次随机采样点数拟合平面需要3个点num_iterations迭代次数// 1. RANSAC平面提取autosegment_resultdown_pcd.SegmentPlane(10.0,// distance_threshold3,// ransac_n1000// num_iterations);// 2. 获取平面模型参数和内点索引Eigen::Vector4d plane_modelsegment_result.first;std::vectorsize_tinlierssegment_result.second;doubleaplane_model(0);doublebplane_model(1);doublecplane_model(2);doubledplane_model(3);// 3. 打印平面方程 (C中格式化输出需要 iomanip 头文件)std::coutstd::fixedstd::setprecision(2);std::cout平面模型: ax by cz d 0std::endl;// 4. 根据索引提取内点点云autoinlier_clouddown_pcd.SelectByIndex(inliers);// 5. 保存点云open3d::io::WritePointCloud(pointcloud_plane.pcd,*inlier_cloud,true,true);std::cout点云保存到pointcloud_plane.pcdstd::endl;最小二乘最小二乘法是一种数学方法用于在给定的数据中找到最佳拟合的平面。算法原理最小二乘也是一种迭代算法但是和ranscan算法不同ranscan算法是随机采样而最小二乘算法是全局搜索。1.模型假设平面方程axbyczd02.计算点云中所有点到该平面的距离计算距离的平方和得到目标函数。3.求取最目标函数值对目标函数求导得到导数为0的方程解出a,b,c,d。4.得到平面参数a,b,c,d。这个算法在求解最小值时可以使用拉格朗日乘子法处理后可以等效为特征值分解而且更方便快速所以是点云处理中常用的算法。1.计算质心2.去中心化3.计算协方差矩阵4.计算特征值和特征向量5.选取特征值最小的特征向量即为法向量6.计算d得到平面参数a,b,c,d。算法特点算法特点这个算法的假设是处理的点云基本已经形成了平面对点云进行全局搜索能得到唯一的平面。这个特点解决了ranscan算法的随机性问题算是主要优点。但是这个算法的缺点也很明显就是鲁棒性差如果点云中存在噪声或者点云没有形成平面那么这个算法就会失效。所以需要配合其他算法先提取点云平面再进行最小二乘。常用的方式是使用法向量过滤先提取点云平面再进行最小二乘。代码实现importnumpyasnpdeffit_plane_pca(points:np.ndarray): 用 PCA / SVD 拟合平面完全确定 返回法向量、d、质心 centroidpoints.mean(axis0)centeredpoints-centroid _,_,Vtnp.linalg.svd(centered,full_matricesFalse)normalVt[2,:]d-np.dot(normal,centroid)returnnormal,d,centroid/** * brief 使用 PCA / SVD 拟合平面 */std::vectordoublefit_plane_pca(conststd::vectorEigen::Vector3dpoints){conststd::size_t Npoints.size();// ---------- 1. 计算质心 ----------Eigen::Vector3d centroidEigen::Vector3d::Zero();for(constautop:points){centroidp;}centroid/static_castdouble(N);// ---------- 2. 去质心 ----------Eigen::MatrixXdcentered(N,3);for(std::size_t i0;iN;i){centered.row(i)(points[i]-centroid).transpose();}// ---------- 3. SVD ----------Eigen::BDCSVDEigen::MatrixXdsvd(centered,Eigen::ComputeThinU|Eigen::ComputeThinV);Eigen::Vector3d normalsvd.matrixV().transpose().row(2).transpose();// ---------- 4. 保证法向量 z 0 ----------if(normal.z()0){normal-normal;}// ---------- 5. 平面参数 ----------doubleanormal.x();doublebnormal.y();doublecnormal.z();doubled-normal.dot(centroid);return{a,b,c,d};}总结ranscan算法和最小二乘算法是两种常用的平面提取算法ranscan算法是随机采样鲁棒性强但是随机性导致结果不稳定最小二乘算法是全局搜索结果稳定但是鲁棒性差需要配合其他算法使用在对精度要求不高的场景中ranscan算法是首选比如导航而在对精度要求高的场景中最小二乘算法是首选比如工业测量。