背景:
我获取了一些物体点云集,我想拿他们来搞深度学习。但是呢,他们每个点云的点数量不统一,无法作为网络的输入。那我们就需要对他们下采样至一个固定数量点的点云。
注:pcl的voxel grid filter可以下采样,但无法保证输出的点云的点的数量。
1. 代码:
#include <iostream> #include <cstdlib> #include <pcl/io/pcd_io.h> #include <pcl/point_types.h> #include <pcl/filters/voxel_grid.h> #include <pcl/visualization/cloud_viewer.h> #include <pcl/common/transforms.h> #define PI 3.1415 using namespace std; typedef pcl::PointXYZ PointT; typedef pcl::PointCloud<PointT> PointCloudT; unsigned int num_out_pt = 1024*2; PointCloudT::Ptr rotateABit(const PointCloudT::Ptr cloud_in){ PointCloudT::Ptr cloud_transformed (new PointCloudT); Eigen::Matrix4f transform = Eigen::Matrix4f::Identity(); float theta_deg = 30; float c = cos(theta_deg*PI / 180.0); float s = sin(theta_deg*PI / 180.0); transform(1,1) = c; transform(3,3) = c; transform(1,3) = -s; transform(3,1) = s; pcl::transformPointCloud(*cloud_in, *cloud_transformed, transform); return cloud_transformed; } int main (int argc, char** argv) { PointCloudT::Ptr cloud_in (new PointCloudT), cloud_out (new PointCloudT); pcl::io::loadPCDFile("unknown_object.pcd", *cloud_in); boost::shared_ptr<pcl::visualization::PCLVisualizer> viewer( new pcl::visualization::PCLVisualizer ("Viewer")); pcl::PointIndices::Ptr indices (new pcl::PointIndices); std::vector<int> idx; unsigned int num_pt = cloud_in->points.size(); cout << "Input point cloud's point number = " << num_pt << endl; int label[num_pt]; for (int i = 0; i < num_pt; i++){ label[i] = 0; } if (num_pt < num_out_pt) return (-1); for (int i = 0; i < num_out_pt; i++){ int a_rand_num = rand() % num_pt; while(1){ if (label[a_rand_num] == 0){ idx.push_back(a_rand_num); label[i] = 1; break; } a_rand_num = rand() % num_pt; } } pcl::copyPointCloud(*cloud_in, idx, *cloud_out); cout << "Ouput point cloud's point number = " << cloud_out->points.size() << endl; viewer->addPointCloud(rotateABit(cloud_in), "cloud_in"); pcl::visualization::PointCloudColorHandlerCustom<PointT> red(cloud_out, 255, 0, 0); viewer->addPointCloud(cloud_out, red, "cloud_out"); while(!viewer->wasStopped()){ viewer->spinOnce(); } return (0); }
2. 算法细节:
在输入的点云的index上做随机抽取。抽取固定数量的不重复的index,再把index对应的点云抽出来。
3. 跑的效果:
扫描二维码关注公众号,回复:
1032261 查看本文章
(上面的点云是结果,下面的是输入)
DownSample/bin/DownSampling...
Input point cloud's point number = 8391
Ouput point cloud's point number = 1024
4. 对比:
但是呢,这种方法虽然简单,但是重要的轮廓信息被削弱了很多,以及点分布不均匀。而voxel grid filter 就没有这些问题了,只是voxel grid filter 无法保证输出的点的数量。
其实这个和pcl官方的Random Sample算法效果一样,后者也能确保输出的点的数量固定一个数值,详见我的另一文章点击打开链接。下图是pcl的Random Sample 的效果: