Qt+vtk+pcl realizes point cloud voxel downsampling

Directory

Add dialog controls

layout ui

mainwindow.h add header file

filter_voxel.h settings

filter_voxel.cpp setting

Add relevant header files to pcl_function.h and declare the downsampling function

Convert pcl to vtk and visualize the code

Pass the parameters entered in the dialog back to the related function


Add dialog controls

Layout ui

mainwindow.h add header file

filter_voxel.h settings

#ifndef FILTER_VOXEL_H
#define FILTER_VOXEL_H

#include <QDialog>

namespace Ui {
class Filter_voxel;
}

class Filter_voxel : public QDialog
{
    Q_OBJECT

signals:
    void sendData(QString data);

public:
    explicit Filter_voxel(QWidget *parent = nullptr);
    ~Filter_voxel();


private slots:
    void on_buttonBox_accepted();

private:
    Ui::Filter_voxel *ui;
};


#endif // FILTER_VOXEL_H

filter_voxel.cpp settings

#include "filter_voxel.h"
#include "ui_filter_voxel.h"

Filter_voxel::Filter_voxel(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::Filter_voxel)
{
    ui->setupUi(this);
}

Filter_voxel::~Filter_voxel()
{
    delete ui;
}

void Filter_voxel::on_buttonBox_accepted()
{
    emit sendData(ui->lineEdit->text());

    this->close();

}

/**********************************pcl format********** *******************/
#include <pcl/common/io.h>
#include <pcl/io/pcd_io.h>
#include <pcl/io/ply_io.h>
#include <pcl/point_types.h>
#include <pcl/point_cloud.h>
#include <pcl/io/vtk_io.h>
#include <pcl/io/vtk_lib_io.h>

/**********************************pcl display************** ***************/
#include <boost/shared_ptr.hpp>
#include <pcl/visualization/pcl_visualizer.h>
#include <pcl/visualization/histogram_visualizer.h>
#include <pcl/visualization/pcl_plotter.h>
#include <pcl/visualization/point_cloud_color_handlers.h>
#include <pcl/visualization/point_cloud_handlers.h>
#include <pcl/visualization/point_cloud_geometry_handlers.h>
/**********************************pcl filter************** ***************/
#include <pcl/filters/voxel_grid.h> //Voxel filtering



pcl::PointCloud<pcl::PointXYZ>::Ptr pcl_filter_voxel(pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_in,float leaf_size);

The down-sampling function is added to pcl_function.cpp, and the code is still small, so they are all posted.

#include "pcl_function.h"

//voxel
pcl::PointCloud<pcl::PointXYZ>::Ptr pcl_filter_voxel(pcl::PointCloud<pcl::PointXYZ>::Ptr cloud, float leaf_size)
{
    pcl::VoxelGrid<pcl::PointXYZ> voxel_grid;
    voxel_grid.setLeafSize(leaf_size,leaf_size,leaf_size);
    voxel_grid.setInputCloud(cloud);
    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_out (new pcl::PointCloud<pcl::PointXYZ> ()) ;
    voxel_grid. filter(*cloud_out);

    return cloud_out;
}

Pcl_function::Pcl_function()
{

}

mainwindow.h add slot function, instance dialog box

private slots:

    void pressBtn_voxel();//menu bar voxel button
    void Voxel_clicked(QString data); //voxel filtering
private:
    //vtk to pcl needs to be used
    vtkSmartPointer<vtkPolyData> polydata = vtkSmartPointer<vtkPolyData>::New();
    // instance dialog
    Filter_voxel *dialog_voxel;

After the point cloud is processed, it has to be converted from pcl to vtk and then visualized. The conversion and visualization part of the code in the open_clicked function in the point cloud reading and visualization process is stripped off and encapsulated into the updatePointCloud function for easy calling.

public:
   
    void updatePointCloud(pcl::PointCloud<pcl::PointXYZ>::Ptr cloud);

In the mainwindow.cpp constructor, add code to create filter in the menu bar -> downsampling -> voxel filter

 QMenu *filter_menu = menu_bar->addMenu("filter");
    filter_menu->addMenu("Downsampling")->addAction("Voxel Filtering", this, MainWindow::pressBtn_voxel);

pcl to vtk and visualize code

void MainWindow::updatePointCloud(pcl::PointCloud<pcl::PointXYZ>::Ptr cloud)
{
    ui->textBrowser->clear();
    // Get the number of points in the point cloud and convert it to a string
    int point_num = cloud->size();
    QString point_num_str = QString::number(point_num);
    // Display the number of points in the point cloud in the textbrowser
    ui->textBrowser->append("The number of points in the point cloud is:" + point_num_str);

    // Convert point cloud data to VTK point data
    vtkSmartPointer<vtkPoints> points = vtkSmartPointer<vtkPoints>::New();
    for (size_t i = 0; i < cloud->size(); + + i) {
        pcl::PointXYZ p = cloud->at(i);
        points->InsertNextPoint(p.x, p.y, p.z);
    }

    // Create VTK point data object
    vtkSmartPointer<vtkPolyData> polydata = vtkSmartPointer<vtkPolyData>::New();
    polydata->SetPoints(points);

    // Use vtkVertexGlyphFilter to turn each point into a small sphere
    vtkSmartPointer<vtkVertexGlyphFilter> vertexFilter = vtkSmartPointer<vtkVertexGlyphFilter>::New();
    vertexFilter->SetInputData(polydata);
    vertexFilter->Update();

    // Create VTK point data mapper
    vtkSmartPointer<vtkPolyDataMapper> mapper = vtkSmartPointer<vtkPolyDataMapper>::New();
    mapper->SetInputConnection(vertexFilter->GetOutputPort());

    // Create VTK actor
    vtkSmartPointer<vtkActor> actor = vtkSmartPointer<vtkActor>::New();
    actor->SetMapper(mapper);

    // add actor to renderer
    vtkSmartPointer<vtkRenderer> renderer = vtkSmartPointer<vtkRenderer>::New();
    renderer->AddActor(actor);

    // Add renderer to vtkRenderWindow
    vtkSmartPointer<vtkGenericOpenGLRenderWindow> renderWindow = vtkSmartPointer<vtkGenericOpenGLRenderWindow>::New();
    renderWindow->AddRenderer(renderer);
    // Display vtkRenderWindow on QVTKOpenGLWidget
    ui->qvtkWidget->SetRenderWindow(renderWindow);
    ui->qvtkWidget->update();


}

The modified function of reading point cloud is more concise

void MainWindow::Open_clicked()
{

    // Select the .pcd file
       QString filename = QFileDialog::getOpenFileName(this, tr("Open PCD file"), ".", tr("PCD file (*.pcd)"));
       if (filename. isEmpty()) {
           return;
       }

       // read point cloud data from file
       pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
       if (pcl::io::loadPCDFile<pcl::PointXYZ>(filename.toStdString(), *cloud) == -1) {
           PCL_ERROR("Could not read .pcd file\\
");
           return;
       }

      
       updatePointCloud(cloud);//call the conversion and visualization function

       pointCloudLoaded = true;

       ui->verticalScrollBar->setEnabled(true);

}

Pass the parameters entered in the dialog back to the relevant functions

//Voxel sampling
void MainWindow::pressBtn_voxel()//Call the newly created qt designer interface
{
    dialog_voxel = new Filter_voxel();
    connect(dialog_voxel, &Filter_voxel::sendData, this, &MainWindow::Voxel_clicked);
    dialog_voxel->exec();
    delete dialog_voxel;
}


void MainWindow::Voxel_clicked(QString data)
{
    //Convert vtk to pcl, because the pcl library is used to process the point cloud
    vtkPolyData* polydata = vtkPolyData::SafeDownCast(ui->qvtkWidget->GetRenderWindow()->GetRenderers()->GetFirstRenderer()->GetActors()->GetLastActor()->GetMapper()->GetInput());

    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
 
    pcl::io::vtkPolyDataToPointCloud(polydata, *cloud);

    float size = data.toFloat();//here is to get the value entered in the designer interface

    auto cloud_out = pcl_filter_voxel(cloud, size);//Call the downsampling function to process the point cloud

    updatePointCloud(cloud_out);//Go to pcl to vtk and visualize the function



}

If you want to add additional point cloud processing, the process is much the same.