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