直接对整个场景的点云进行特征提取,效果很差,因此通过划分区域格网进行划分。格网划分有很多种方式,在这里尝试使用哈希表进行格网链接,后续通过在每个格网内基于点云特征进行提取。

参考博客:
点云侠的PCL 点云分块_pcl 点云按网格分块_点云侠的博客-CSDN博客

点云学徒的PCL点云处理之创建二维格网组织点云数据(六十四)_哈希表 c++ pcl 点云_点云学徒的博客-CSDN博客

使用了c++的哈希表代替了的qt库中哈希表


代码如下:

#include <iostream>
#include <fstream>
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
#include <pcl/common/pca.h>
#include <pcl/common/common.h>
#include <unordered_map>
#include <list>
#include <functional>
#include <cstdlib>
#include <pcl/point_cloud.h>



using namespace std;
using namespace Eigen;

int main(int argc, char** argv) {
    // 定义点云容器
    pcl::PointCloud<pcl::PointXYZI>::Ptr PC(new pcl::PointCloud<pcl::PointXYZI>);  // 原始点云容器

    // 读入原始点云
    if (pcl::io::loadPCDFile<pcl::PointXYZI>("iScan.pcd", *PC) == -1) {
        cout << "打开失败" << endl;
        return false;
    }

    // 根据原始点云坐标最值创建格网
    pcl::PointXYZI minPt, maxPt;  // 存储点云最值
    int RowNum = 2;               // 格网的行数
    int ColNum = 2;               // 格网的列数

    pcl::getMinMax3D(*PC, minPt, maxPt);

    cout << " 格网创建完成 " << endl;

    // 哈希表存储点云
    unordered_map<unsigned int, pcl::PointCloud<pcl::PointXYZI>> Point2dHash;  // 存放点云的二维哈希表
    list<unsigned int> no_empty_List;                                          // 判断二维格网内部是否有点的链表 将有点格网对应的哈希号存储进去
    int row, col;                                                               // 点云对应的格网行、列号
    size_t TempIndex;                                                           // 哈希键  意思就是将二维索引变成一维索引

    for (size_t Index = 0; Index < PC->points.size(); Index++) {
        // 计算点云所在的行、列
        row = int(RowNum * (PC->points[Index].x - minPt.x) / (maxPt.x - minPt.x));
        col = int(ColNum * (PC->points[Index].y - minPt.y) / (maxPt.y - minPt.y));

        // 防止越界
        row = max(0, min(row, RowNum - 1));
        col = max(0, min(col, ColNum - 1));

        TempIndex = row * ColNum + col;

        if (find(no_empty_List.begin(), no_empty_List.end(), TempIndex) == no_empty_List.end()) {
            no_empty_List.push_back(TempIndex);
        }

        Point2dHash[TempIndex].push_back(PC->points[Index]);
    }

    cout << " 哈希表完成 " << endl;

    // 显示每个格网内的点云数量
    for (const auto& entry : no_empty_List)
    {
        size_t count = Point2dHash[entry].size();
        cout << "Grid[" << entry << "] has " << count << " points." << endl;
    }

    // 将每个格网内的点云合并保存为新的点云文件
    pcl::PointCloud<pcl::PointXYZI>::Ptr resultCloud(new pcl::PointCloud<pcl::PointXYZI>);
    for (const auto& entry : no_empty_List) {
        if (!Point2dHash[entry].empty()) {
            *resultCloud += Point2dHash[entry];
        }
    }


    // 将每个格网内的点云合并保存为新的点云文件 pcd格式有坐标偏移的现状
    pcl::PCDWriter writer;

    string base_path = "G:\\test\\";  // 指定基本路径

    for (const auto& entry : no_empty_List) {
        if (!Point2dHash[entry].empty()) {
            string file_path = base_path + "result_cloud_grid_" + to_string(entry) + ".pcd";

          
          writer.write<pcl::PointXYZI>(file_path, Point2dHash[entry], true);
          

            cout << "Grid[" << entry << "] saved to " << file_path << endl;
        }
    }


  


    return 0;
}

​​​​​运行结果如下:
学习记录PCL-1 通过哈希表进行三维点云的虚拟格网划分-LMLPHP

12-08 04:22