• 利用Eigen库,PCA构建点云法向量


    疫情在家,想做科研,可是资料都在学校电脑里面。只能看看能不能回想起什么写点什么。

    这次主要是想把提取出的点云patch单独进行点云法向量的计算,因为已经构成patch,则不需使用knn或者设定邻域半径。

    接下来手撕 PCA 来构建点云法向量。

     1 #define _CRT_SECURE_NO_WARNINGS
     2 #define _SCL_SECURE_NO_WARNINGS
     3 #include <pcl/io/pcd_io.h>
     4 #include <pcl/point_types.h>
     5 #include <pcl/features/normal_3d.h>
     6 #include <Eigen/core>
     7 
     8 #include <vector>
     9 
    10 using namespace std;
    11 
    12 int main() 
    13 {
    14     pcl::PCDReader reader;
    15     pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
    16     reader.read("../../data/23b_12.pcd", *cloud);
    17 
    18     int cld_sz = cloud->size();
    19     pcl::PointCloud<pcl::Normal>::Ptr normals(new pcl::PointCloud<pcl::Normal>);
    20     normals->resize(cld_sz);
    21 
    22     //计算中心点坐标
    23     double center_x = 0, center_y = 0, center_z = 0;
    24     for (int i = 0; i < cld_sz; i++) {
    25         center_x += cloud->points[i].x;
    26         center_y += cloud->points[i].y;
    27         center_z += cloud->points[i].z;
    28     }
    29     center_x /= cld_sz;
    30     center_y /= cld_sz;
    31     center_z /= cld_sz;
    32     //计算协方差矩阵
    33     double xx = 0, xy = 0, xz = 0, yy = 0, yz = 0, zz = 0;
    34     for (int i = 0; i < cld_sz; i++) {
    35         xx += (cloud->points[i].x - center_x) * (cloud->points[i].x - center_x);
    36         xy += (cloud->points[i].x - center_x) * (cloud->points[i].y - center_y);
    37         xz += (cloud->points[i].x - center_x) * (cloud->points[i].z - center_z);
    38         yy += (cloud->points[i].y - center_y) * (cloud->points[i].y - center_y);
    39         yz += (cloud->points[i].y - center_y) * (cloud->points[i].z - center_z);
    40         zz += (cloud->points[i].z - center_z) * (cloud->points[i].z - center_z);
    41     }
    42     //大小为3*3的协方差矩阵
    43     Eigen::Matrix3f covMat(3, 3);
    44     covMat(0, 0) = xx / cld_sz;
    45     covMat(0, 1) = covMat(1, 0) = xy / cld_sz;
    46     covMat(0, 2) = covMat(2, 0) = xz / cld_sz;
    47     covMat(1, 1) = yy / cld_sz;
    48     covMat(1, 2) = covMat(2, 1) = yz / cld_sz;
    49     covMat(2, 2) = zz / cld_sz;
    50 
    51     //求特征值与特征向量
    52     Eigen::EigenSolver<Eigen::Matrix3f> es(covMat);
    53     Eigen::Matrix3f val = es.pseudoEigenvalueMatrix();
    54     Eigen::Matrix3f vec = es.pseudoEigenvectors();
    55 
    56     //找到最小特征值t1
    57     double t1 = val(0, 0);
    58     int ii = 0;
    59     if (t1 > val(1, 1)) {
    60         ii = 1;
    61         t1 = val(1, 1);
    62     }
    63     if (t1 > val(2, 2)){
    64         ii = 2;
    65         t1 = val(2, 2);
    66     }
    67 
    68     //最小特征值对应的特征向量v_n
    69     Eigen::Vector3f v(vec(0, ii), vec(1, ii), vec(2, ii));
    70     //特征向量单位化
    71     v /= v.norm();
    72  for (int i = 0; i < cld_sz; i++) { 74 normals->points[i].normal_x = v(0); 75 normals->points[i].normal_y = v(1); 76 normals->points[i].normal_z = v(2); 77 normals->points[i].curvature = t1 / (val(0, 0) + val(1, 1) + val(2, 2)); 78 } 79 80 cin.get(); 81 return 0; 82 }

    当然写的不是很严谨,仅供大家参考。

    想来生活无非是痛苦和美丽...
  • 相关阅读:
    Java AbstractQueuedSynchronizer(AQS)
    CentOS Install Rancher & K3s
    CentOS Install Rancher & Kubernetes
    CentOS Install Kubernetes & Kubesphere
    支付宝小程序入门
    uni-app 抽奖
    APP上架
    uniapp微信小程序语音识别实现
    uniapp 安卓打包之导入的项目打包指导
    uniapp 支付宝 支付后不成功回调
  • 原文地址:https://www.cnblogs.com/billwong/p/12622385.html
Copyright © 2020-2023  润新知