直接对整个场景的点云进行特征提取,效果很差,因此通过划分区域格网进行划分。格网划分有很多种方式,在这里尝试使用哈希表进行格网链接,后续通过在每个格网内基于点云特征进行提取。
参考博客:
点云侠的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;
}
运行结果如下: