代码分享:点云下采样至一个固定数量点的点云

背景:

我获取了一些物体点云集,我想拿他们来搞深度学习。但是呢,他们每个点云的点数量不统一,无法作为网络的输入。那我们就需要对他们下采样至一个固定数量点的点云。


注: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. 跑的效果:


(上面的点云是结果,下面的是输入)

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 的效果:



猜你喜欢

转载自blog.csdn.net/AmbitiousRuralDog/article/details/80376144