天天看點

PCL體素濾波(VoxelGrid filter)進行下采樣及其可視化

2019.10.25更新(帶指令行參數)

//體素濾波(下采樣)
#include <iostream>
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
#include <pcl/filters/voxel_grid.h>
#include <pcl/visualization/pcl_visualizer.h>


int main(int argc,char** argv) {
    if(argc<2){
        std::cout<<"參數個數太少: ./demo_voxel_grid pcd"<<std::endl;
        return -1;
    }
    //拼接字元串作為輸出結果的儲存


    std::cout<<argv[1]<<std::endl;
    std::cout<< typeid(argv[1]).name()<<std::endl;
    
    std::cout << "Hello, World!" << std::endl;

    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_in(new pcl::PointCloud<pcl::PointXYZ>);
    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered(new pcl::PointCloud<pcl::PointXYZ>);

    pcl::io::loadPCDFile(argv[1],*cloud_in);
    std::cerr<<"PointCloud before filtering: "<<cloud_in->size()<<" data points ("<<pcl::getFieldsList(*cloud_in)<<" )"<<std::endl;

    //???????
    pcl::VoxelGrid<pcl::PointXYZ> sor;
    sor.setInputCloud(cloud_in);
    sor.setLeafSize(0.01,0.01,0.01);
    sor.filter(*cloud_filtered);
    std::cout<<"voxel filter succeed!"<<std::endl;
    std::cerr<<"PointCloud after filtering: "<<cloud_filtered->size()<<" data points ("<<pcl::getFieldsList(*cloud_filtered)<<" )"<<std::endl;

    //考慮如何将兩個字元串組合起來
    std::string result;
    const std::string str1 = "down_sample_";
    const std::string str2 = argv[1];
    result = str1;
    result += str2;
    std::cout<<result<<std::endl;

    pcl::io::savePCDFileASCII(result,*cloud_filtered);
    std::cout<<result<<" save succeed!"<<std::endl;

    //?????
    pcl::visualization::PCLVisualizer::Ptr viewer(new pcl::visualization::PCLVisualizer("demo"));
    viewer->initCameraParameters();
    int v1(0);//?????????????
    viewer->createViewPort(0.0,0.0,0.5,1,v1); //??????????????С??λ????????
    viewer->setBackgroundColor(255,0,255,v1);//background of first port
    viewer->addText("cloud_in",10,10,"cloud_in",v1);//????????????
    pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> single_color1(cloud_in,0,255,0);//????????????????
    viewer->addPointCloud<pcl::PointXYZ>(cloud_in,single_color1,"cloud_in",v1);//????????????

    int v2(0);//?????????????
    viewer->createViewPort(0.5,0.0,1,1,v2); //??????????????С??λ????????
    viewer->setBackgroundColor(0,0,0,v2);//background of first port
    viewer->addText("cloud_filtered",10,10,"cloud_filtered",v2);//????????????
    pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> single_color2(cloud_filtered,255,0,0);//????????????????
    viewer->addPointCloud<pcl::PointXYZ>(cloud_filtered,single_color2,"cloud_filtered",v2);//????????????

    viewer->addCoordinateSystem();

    viewer->spin();


    return 0;
}
           
//VoxelGrid filter(體素濾波)
//大緻是通過設定一個小正方體的各個邊的長度,使其重心來将正方體中的points替代。
#include <iostream>
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
#include <pcl/filters/voxel_grid.h>
#include <pcl/visualization/pcl_visualizer.h>


int main() {
    std::cout << "Hello, World!" << std::endl;

    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_in(new pcl::PointCloud<pcl::PointXYZ>);
    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filtered(new pcl::PointCloud<pcl::PointXYZ>);

    pcl::io::loadPCDFile("room_scan1.pcd",*cloud_in);
    std::cerr<<"PointCloud before filtering: "<<cloud_in->size()<<" data points ("<<pcl::getFieldsList(*cloud_in)<<" )"<<std::endl;//cerr輸出為紅色

    //體素濾波
    pcl::VoxelGrid<pcl::PointXYZ> sor;
    sor.setInputCloud(cloud_in);
    sor.setLeafSize(0.05,0.05,0.05);
    sor.filter(*cloud_filtered);
    std::cout<<"voxel filter succeed!"<<std::endl;
    std::cerr<<"PointCloud after filtering: "<<cloud_filtered->size()<<" data points ("<<pcl::getFieldsList(*cloud_filtered)<<" )"<<std::endl;//getFieldsList(*cloud_filtered) 擷取點的field(類似于次元)

    pcl::io::savePCDFileASCII("room_scan1_filtered",*cloud_filtered);
    std::cout<<"save succeed!"<<std::endl;

    //可視化
    pcl::visualization::PCLVisualizer::Ptr viewer(new pcl::visualization::PCLVisualizer("demo"));
    viewer->initCameraParameters();
    int v1(0);//第一個視窗的參數
    viewer->createViewPort(0.0,0.0,0.5,1,v1); //設定第一個視窗的大小,位于螢幕左側
    viewer->setBackgroundColor(255,0,255,v1);//background of first port
    viewer->addText("cloud_in",10,10,"cloud_in",v1);//好像是一個便簽
    pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> single_color1(cloud_in,0,255,0);//設定第一個點雲的顔色
    viewer->addPointCloud<pcl::PointXYZ>(cloud_in,single_color1,"cloud_in",v1);//顯示第一個點雲

    int v2(0);//第一個視窗的參數
    viewer->createViewPort(0.5,0.0,1,1,v2); //設定第一個視窗的大小,位于螢幕左側
    viewer->setBackgroundColor(0,0,0,v2);//background of first port
    viewer->addText("cloud_filtered",10,10,"cloud_filtered",v2);//好像是一個便簽
    pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> single_color2(cloud_filtered,255,0,0);//設定第一個點雲的顔色
    viewer->addPointCloud<pcl::PointXYZ>(cloud_filtered,single_color2,"cloud_filtered",v2);//顯示第一個點雲

    viewer->addCoordinateSystem();

    viewer->spin();


    return 0;
}
           

 可視化結果1(體素=0.05):(依次為原資料、下采樣之後的資料)

PCL體素濾波(VoxelGrid filter)進行下采樣及其可視化

 可視化結果2(體素=0.01):

PCL體素濾波(VoxelGrid filter)進行下采樣及其可視化

總結:體素越大,濾除掉的點越少,反之亦然。

下采樣可以作為一些大型資料運算處理之前的預處理,以減少運算時間和成本。使用體素下采樣仍可以儲存點雲資料的大緻樣貌。 

例程裡面的PointCloud2類型的資料不會可視化,是以選取了PointXYZ類型的資料。知道如何可視化PointCloud2類型的資料的朋友可以指點一下。:)

繼續閱讀