多点法相到曲面展开
这个也是我现在做的一个项目其核心原理就是参考halcon 中的案例做的曲面矫正一、问题一个曲面点云 每个点的法向量目标把曲面“展开”为一个近似平面目标把曲面“展开”为一个近似平面二、核心难点-局部坐标系的建立基础单点点 法向 → 一个坐标系https://blog.csdn.net/weixin_39354845/article/details/159355727?sharetypeblogdetailsharerId159355727sharereferPCsharesourceweixin_39354845spm1011.2480.3001.8118那么点云有500个点的话就有500个局部坐标系那么如何把这500个坐标系连续起来这就需要我们做好坐标系一致性三、算法流程Step 1 点云 法向输入Pi, ni来源结构光重建或 PCL 法向估计Step 2 法向统一非常关键问题n 和 -n 不确定解决构造邻接图kNN传播方向if dot(ni, nj) 0 → nj -nj保证整个曲面法向一致Step 3 构造局部坐标系每个点对每个点zi nixi 任意 ⟂ ziyi zi × xi得到Ri [xi yi zi]Step 4 局部参数化关键目标把3D点映射到2D平面局部投影对每个点ui xi · (Pi - P0)vi yi · (Pi - P0)得到( ui, vi ) → 展开坐标❗问题误差会积累会扭曲四、进阶全局展开E Σ || (Pi - Pj) - R*(ui-uj, vi-vj) ||²本质保持局部几何关系不变常见算法1 LSCM最常用Least Squares Conformal Mapping特点保角角度不变展开自然2 ARAP更高级As-Rigid-As-Possible特点尽量保持局部刚性五、工业流程和Matlab 、PCL测试1. ROI裁剪只取局部曲面 2. PCA → 得到主方向 3. 用主平面作为全局坐标系 4. 所有点投影到这个平面 5. 局部用法向做微调补偿 数学表达 u (P - μ) · e1 v (P - μ) · e2 其中 e1, e2 PCA主方向matlabclc; clear; close all; % 构造曲面 [X,Y] meshgrid(-2:0.2:2, -2:0.2:2); Z 0.5*X.^2 0.2*Y.^2; pts [X(:), Y(:), Z(:)]; % PCA mu mean(pts); Q pts - mu; C cov(Q); [V,D] eig(C); [~, idx] sort(diag(D), descend); V V(:, idx); e1 V(:,1); e2 V(:,2); % 展开 u Q * e1; v Q * e2; % 可视化 figure; subplot(1,2,1); scatter3(pts(:,1), pts(:,2), pts(:,3), .); title(原始曲面); subplot(1,2,2); scatter(u, v, .); title(展开后近似平面); axis equal;PCL流程1. 法向估计 / 输入法向 2. 法向统一方向一致 3. PCA求全局参考平面 4. 构造局部坐标场可选增强 5. 投影到2D展开 6. 可选平滑 / 优化法向量估计pcl::PointCloudpcl::PointXYZ::Ptr cloud(new pcl::PointCloudpcl::PointXYZ); pcl::io::loadPCDFile(input.pcd, *cloud); pcl::NormalEstimationpcl::PointXYZ, pcl::Normal ne; ne.setInputCloud(cloud); pcl::search::KdTreepcl::PointXYZ::Ptr tree(new pcl::search::KdTreepcl::PointXYZ()); ne.setSearchMethod(tree); pcl::PointCloudpcl::Normal::Ptr normals(new pcl::PointCloudpcl::Normal); ne.setKSearch(20); ne.compute(*normals);法向量统一for (size_t i 0; i normals-size(); i) { Eigen::Vector3f ni(normals-points[i].normal_x, normals-points[i].normal_y, normals-points[i].normal_z); // 假设统一朝向相机0,0,1 Eigen::Vector3f view(0,0,1); if (ni.dot(view) 0) ni -ni; normals-points[i].normal_x ni.x(); normals-points[i].normal_y ni.y(); normals-points[i].normal_z ni.z(); }PCA(全局坐标系)Eigen::Vector4f centroid; pcl::compute3DCentroid(*cloud, centroid); Eigen::Matrix3f covariance; pcl::computeCovarianceMatrixNormalized(*cloud, centroid, covariance); Eigen::SelfAdjointEigenSolverEigen::Matrix3f solver(covariance); Eigen::Matrix3f eigenVectors solver.eigenvectors(); // 按特征值排序大→小 Eigen::Vector3f e1 eigenVectors.col(2); Eigen::Vector3f e2 eigenVectors.col(1); Eigen::Vector3f e3 eigenVectors.col(0); // 法向方向构造2D坐标展开核心std::vectorEigen::Vector2f uv_points; for (size_t i 0; i cloud-size(); i) { Eigen::Vector3f p(cloud-points[i].x, cloud-points[i].y, cloud-points[i].z); Eigen::Vector3f q p - centroid.head3(); float u q.dot(e1); float v q.dot(e2); uv_points.emplace_back(u, v); }上面方法只用 PCA全局问题曲率大 → 会拉伸改进局部坐标修正思路PCA → 全局方向法向 → 局部微调局部坐标构造Eigen::Vector3f z normal; Eigen::Vector3f x e1.cross(z).normalized(); Eigen::Vector3f y z.cross(x); 然后 float u q.dot(x); float v q.dot(y);局部更贴合曲面核心认知这一块最重要1 局部 vs 全局法向 → 局部正确PCA → 全局稳定2 展开的本质3D曲面 → 找一个低失真映射 → 2D3 不可能完美曲面展开 ≈ 一定有失真除非是可展曲面比如圆柱
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2443135.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!