Point cloud visualization tool 2

1. Preface

Haha, when I came up with this small tool, on the one hand, the commonly used point cloud viewing software was not in line with my own operating habits. On the other hand, it was more convenient to do some simple point cloud processing test verification on the button. Previous blog < Point Cloud Visualization Tools > A csdner asked about the tutorial on point cloud visualization tools. Let’s find time to update it today on Sunday.=D

2. Development environment

2.1 QT + PCL

  • The program interface is written using Qt, mainly some buttons and appearance adjustments
  • Point cloud processing mainly relies on the PCL point cloud library
  • For information about the installation and environment configuration of qt and pcl, please refer to < QT Configuration PCL1.8.1 >
    • If you don’t want to recompile the pcl vtk library used by Qt, you can use the same version and already compiled library as me.

3. Procedure

3.1 New project

Insert image description here
Insert image description here
Insert image description here
Insert image description here

Insert image description here
Insert image description here

Insert image description here
Insert image description here

3.2 Modify .pro file

  • The original .pro file looks like this. Add the header file directory and dependent library files below.

Insert image description here

3.2.1 Add header file directory

  • INCLUDEPATH += 头文件目录路径
  • You can add pcl, opencv and other libraries that will be used (replace the path with your own installation path)

Insert image description here

INCLUDEPATH += D:\PCL\PCL1.8.1\include\pcl-1.8

INCLUDEPATH += D:\PCL\PCL1.8.1\include\pcl-1.8\pcl

INCLUDEPATH += D:\PCL\PCL1.8.1\3rdParty\Boost\include\boost-1_64

INCLUDEPATH += D:\PCL\PCL1.8.1\3rdParty\Boost\include\boost-1_64\boost

INCLUDEPATH += D:\PCL\PCL1.8.1\3rdParty\Eigen\eigen3

INCLUDEPATH += D:\PCL\PCL1.8.1\3rdParty\FLANN\include

INCLUDEPATH += D:\PCL\PCL1.8.1\3rdParty\FLANN\include\flann

INCLUDEPATH += D:\PCL\PCL1.8.1\3rdParty\OpenNI2\Include

INCLUDEPATH += D:\PCL\PCL1.8.1\3rdParty\Qhull\include

INCLUDEPATH += D:\PCL\PCL1.8.1\3rdParty\VTK1\include\vtk-8.0

INCLUDEPATH += D:\OpenCV\opencv\build\include

INCLUDEPATH += D:\pthread\Pre-built.2\include

INCLUDEPATH += D:\log4cpp\include

3.2.2 Add dependent library files

  • LIBS += -L lib文件目录路径
  • -l lib文件名

Insert image description here

CONFIG(debug,debug|release){
    
    

LIBS += -LD:\PCL\PCL1.8.1\lib\
        -lpcl_common_debug\
        -lpcl_features_debug\
        -lpcl_filters_debug\
        -lpcl_io_debug\
        -lpcl_io_ply_debug\
        -lpcl_kdtree_debug\
        -lpcl_keypoints_debug\
        -lpcl_ml_debug\
        -lpcl_octree_debug\
        -lpcl_outofcore_debug\
        -lpcl_people_debug\
        -lpcl_recognition_debug\
        -lpcl_registration_debug\
        -lpcl_sample_consensus_debug\
        -lpcl_search_debug\
        -lpcl_segmentation_debug\
        -lpcl_stereo_debug\
        -lpcl_surface_debug\
        -lpcl_tracking_debug\
        -lpcl_visualization_debug

LIBS += -LD:\PCL\PCL1.8.1\3rdParty\Boost\lib\
        -llibboost_atomic-vc141-mt-1_64\
        -llibboost_bzip2-vc141-mt-1_64\
        -llibboost_chrono-vc141-mt-1_64\
        -llibboost_container-vc141-mt-1_64\
        -llibboost_context-vc141-mt-1_64\
        -llibboost_coroutine-vc141-mt-1_64\
        -llibboost_date_time-vc141-mt-1_64\
        -llibboost_exception-vc141-mt-1_64\
        -llibboost_fiber-vc141-mt-1_64\
        -llibboost_filesystem-vc141-mt-1_64\
        -llibboost_graph-vc141-mt-1_64\
        -llibboost_graph_parallel-vc141-mt-1_64\
        -llibboost_iostreams-vc141-mt-1_64\
        -llibboost_locale-vc141-mt-1_64\
        -llibboost_log-vc141-mt-1_64\
        -llibboost_log_setup-vc141-mt-1_64\
        -llibboost_math_c99-vc141-mt-1_64\
        -llibboost_math_c99f-vc141-mt-1_64\
        -llibboost_math_c99l-vc141-mt-1_64\
        -llibboost_math_tr1-vc141-mt-1_64\
        -llibboost_math_tr1f-vc141-mt-1_64\
        -llibboost_math_tr1l-vc141-mt-1_64\
        -llibboost_mpi-vc141-mt-1_64\
        -llibboost_numpy-vc141-mt-1_64\
        -llibboost_numpy3-vc141-mt-1_64\
        -llibboost_prg_exec_monitor-vc141-mt-1_64\
        -llibboost_program_options-vc141-mt-1_64\
        -llibboost_python-vc141-mt-1_64\
        -llibboost_python3-vc141-mt-1_64\
        -llibboost_random-vc141-mt-1_64\
        -llibboost_regex-vc141-mt-1_64\
        -llibboost_serialization-vc141-mt-1_64\
        -llibboost_signals-vc141-mt-1_64\
        -llibboost_system-vc141-mt-1_64\
        -llibboost_test_exec_monitor-vc141-mt-1_64\
        -llibboost_thread-vc141-mt-1_64\
        -llibboost_timer-vc141-mt-1_64\
        -llibboost_type_erasure-vc141-mt-1_64\
        -llibboost_unit_test_framework-vc141-mt-1_64\
        -llibboost_wave-vc141-mt-1_64\
        -llibboost_wserialization-vc141-mt-1_64\
        -llibboost_zlib-vc141-mt-1_64

LIBS += -LD:\PCL\PCL1.8.1\3rdParty\FLANN\lib\
        -lflann\
        -lflann_cpp\
        -lflann_cpp_s\
        -lflann_s

LIBS += -LD:\PCL\PCL1.8.1\3rdParty\OpenNI2\Lib\
        -lOpenNI2

LIBS += -LD:\PCL\PCL1.8.1\3rdParty\Qhull\lib\
        -lqhull_d\
        -lqhullcpp_d\
        -lqhullstatic_d\
        -lqhullstatic_r_d\
        -lqhull_p_d\
        -lqhull_r_d

LIBS += -LD:\PCL\PCL1.8.1\3rdParty\VTK1\lib\
        -lvtkalglib-8.0-gd\
        -lvtkChartsCore-8.0-gd\
        -lvtkCommonColor-8.0-gd\
        -lvtkCommonComputationalGeometry-8.0-gd\
        -lvtkCommonCore-8.0-gd\
        -lvtkCommonDataModel-8.0-gd\
        -lvtkCommonExecutionModel-8.0-gd\
        -lvtkCommonMath-8.0-gd\
        -lvtkCommonMisc-8.0-gd\
        -lvtkCommonSystem-8.0-gd\
        -lvtkCommonTransforms-8.0-gd\
        -lvtkDICOMParser-8.0-gd\
        -lvtkDomainsChemistry-8.0-gd\
        -lvtkexoIIc-8.0-gd\
        -lvtkexpat-8.0-gd\
        -lvtkFiltersAMR-8.0-gd\
        -lvtkFiltersCore-8.0-gd\
        -lvtkFiltersExtraction-8.0-gd\
        -lvtkFiltersFlowPaths-8.0-gd\
        -lvtkFiltersGeneral-8.0-gd\
        -lvtkFiltersGeneric-8.0-gd\
        -lvtkFiltersGeometry-8.0-gd\
        -lvtkFiltersHybrid-8.0-gd\
        -lvtkFiltersHyperTree-8.0-gd\
        -lvtkFiltersImaging-8.0-gd\
        -lvtkFiltersModeling-8.0-gd\
        -lvtkFiltersParallel-8.0-gd\
        -lvtkFiltersParallelImaging-8.0-gd\
        -lvtkFiltersPoints-8.0-gd\
        -lvtkFiltersProgrammable-8.0-gd\
        -lvtkFiltersSelection-8.0-gd\
        -lvtkFiltersSMP-8.0-gd\
        -lvtkFiltersSources-8.0-gd\
        -lvtkFiltersStatistics-8.0-gd\
        -lvtkFiltersTexture-8.0-gd\
        -lvtkFiltersTopology-8.0-gd\
        -lvtkFiltersVerdict-8.0-gd\
        -lvtkfreetype-8.0-gd\
        -lvtkGeovisCore-8.0-gd\
        -lvtkgl2ps-8.0-gd\
        -lvtkGUISupportQt-8.0-gd\
#        -lvtkGUISupportQtOpenGL-8.0-gd\
        -lvtkGUISupportQtSQL-8.0-gd\
        -lvtkhdf5-8.0-gd\
        -lvtkhdf5_hl-8.0-gd\
        -lvtkImagingColor-8.0-gd\
        -lvtkImagingCore-8.0-gd\
        -lvtkImagingFourier-8.0-gd\
        -lvtkImagingGeneral-8.0-gd\
        -lvtkImagingHybrid-8.0-gd\
        -lvtkImagingMath-8.0-gd\
        -lvtkImagingMorphological-8.0-gd\
        -lvtkImagingSources-8.0-gd\
        -lvtkImagingStatistics-8.0-gd\
        -lvtkImagingStencil-8.0-gd\
        -lvtkInfovisCore-8.0-gd\
        -lvtkInfovisLayout-8.0-gd\
        -lvtkInteractionImage-8.0-gd\
        -lvtkInteractionStyle-8.0-gd\
        -lvtkInteractionWidgets-8.0-gd\
        -lvtkIOAMR-8.0-gd\
        -lvtkIOCore-8.0-gd\
        -lvtkIOEnSight-8.0-gd\
        -lvtkIOExodus-8.0-gd\
        -lvtkIOExport-8.0-gd\
        -lvtkIOExportOpenGL-8.0-gd\
        -lvtkIOGeometry-8.0-gd\
        -lvtkIOImage-8.0-gd\
        -lvtkIOImport-8.0-gd\
        -lvtkIOInfovis-8.0-gd\
        -lvtkIOLegacy-8.0-gd\
        -lvtkIOLSDyna-8.0-gd\
        -lvtkIOMINC-8.0-gd\
        -lvtkIOMovie-8.0-gd\
        -lvtkIONetCDF-8.0-gd\
        -lvtkIOParallel-8.0-gd\
        -lvtkIOParallelXML-8.0-gd\
        -lvtkIOPLY-8.0-gd\
        -lvtkIOSQL-8.0-gd\
        -lvtkIOTecplotTable-8.0-gd\
        -lvtkIOVideo-8.0-gd\
        -lvtkIOXML-8.0-gd\
        -lvtkIOXMLParser-8.0-gd\
        -lvtkjpeg-8.0-gd\
        -lvtkjsoncpp-8.0-gd\
        -lvtklibharu-8.0-gd\
        -lvtklibxml2-8.0-gd\
        -lvtklz4-8.0-gd\
        -lvtkmetaio-8.0-gd\
        -lvtkNetCDF-8.0-gd\
        -lvtknetcdf_c++-gd\
        -lvtkoggtheora-8.0-gd\
        -lvtkParallelCore-8.0-gd\
        -lvtkpng-8.0-gd\
        -lvtkproj4-8.0-gd\
        -lvtkRenderingAnnotation-8.0-gd\
        -lvtkRenderingContext2D-8.0-gd\
        -lvtkRenderingContextOpenGL-8.0-gd\
        -lvtkRenderingCore-8.0-gd\
        -lvtkRenderingFreeType-8.0-gd\
        -lvtkRenderingGL2PS-8.0-gd\
        -lvtkRenderingImage-8.0-gd\
        -lvtkRenderingLabel-8.0-gd\
        -lvtkRenderingLIC-8.0-gd\
        -lvtkRenderingLOD-8.0-gd\
        -lvtkRenderingOpenGL-8.0-gd\
        -lvtkRenderingQt-8.0-gd\
        -lvtkRenderingVolume-8.0-gd\
        -lvtkRenderingVolumeOpenGL-8.0-gd\
        -lvtksqlite-8.0-gd\
        -lvtksys-8.0-gd\
        -lvtktiff-8.0-gd\
        -lvtkverdict-8.0-gd\
        -lvtkViewsContext2D-8.0-gd\
        -lvtkViewsCore-8.0-gd\
        -lvtkViewsInfovis-8.0-gd\
        -lvtkViewsQt-8.0-gd\
        -lvtkzlib-8.0-gd\

} else {
    
    
LIBS += -LD:\PCL\PCL1.8.1\lib\
        -lpcl_common_release\
        -lpcl_features_release\
        -lpcl_filters_release\
        -lpcl_io_ply_release\
        -lpcl_io_release\
        -lpcl_kdtree_release\
        -lpcl_keypoints_release\
        -lpcl_ml_release\
        -lpcl_octree_release\
        -lpcl_outofcore_release\
        -lpcl_people_release\
        -lpcl_recognition_release\
        -lpcl_registration_release\
        -lpcl_sample_consensus_release\
        -lpcl_search_release\
        -lpcl_segmentation_release\
        -lpcl_stereo_release\
        -lpcl_surface_release\
        -lpcl_tracking_release\
        -lpcl_visualization_release

LIBS += -LD:\PCL\PCL1.8.1\3rdParty\Boost\lib\
        -llibboost_atomic-vc141-mt-1_64\
        -llibboost_bzip2-vc141-mt-1_64\
        -llibboost_chrono-vc141-mt-1_64\
        -llibboost_container-vc141-mt-1_64\
        -llibboost_context-vc141-mt-1_64\
        -llibboost_coroutine-vc141-mt-1_64\
        -llibboost_date_time-vc141-mt-1_64\
        -llibboost_exception-vc141-mt-1_64\
        -llibboost_fiber-vc141-mt-1_64\
        -llibboost_filesystem-vc141-mt-1_64\
        -llibboost_graph-vc141-mt-1_64\
        -llibboost_graph_parallel-vc141-mt-1_64\
        -llibboost_iostreams-vc141-mt-1_64\
        -llibboost_locale-vc141-mt-1_64\
        -llibboost_log-vc141-mt-1_64\
        -llibboost_log_setup-vc141-mt-1_64\
        -llibboost_math_c99-vc141-mt-1_64\
        -llibboost_math_c99f-vc141-mt-1_64\
        -llibboost_math_c99l-vc141-mt-1_64\
        -llibboost_math_tr1-vc141-mt-1_64\
        -llibboost_math_tr1f-vc141-mt-1_64\
        -llibboost_math_tr1l-vc141-mt-1_64\
        -llibboost_mpi-vc141-mt-1_64\
        -llibboost_numpy-vc141-mt-1_64\
        -llibboost_numpy3-vc141-mt-1_64\
        -llibboost_prg_exec_monitor-vc141-mt-1_64\
        -llibboost_program_options-vc141-mt-1_64\
        -llibboost_python-vc141-mt-1_64\
        -llibboost_python3-vc141-mt-1_64\
        -llibboost_random-vc141-mt-1_64\
        -llibboost_regex-vc141-mt-1_64\
        -llibboost_serialization-vc141-mt-1_64\
        -llibboost_signals-vc141-mt-1_64\
        -llibboost_system-vc141-mt-1_64\
        -llibboost_test_exec_monitor-vc141-mt-1_64\
        -llibboost_thread-vc141-mt-1_64\
        -llibboost_timer-vc141-mt-1_64\
        -llibboost_type_erasure-vc141-mt-1_64\
        -llibboost_unit_test_framework-vc141-mt-1_64\
        -llibboost_wave-vc141-mt-1_64\
        -llibboost_wserialization-vc141-mt-1_64\
        -llibboost_zlib-vc141-mt-1_64

LIBS += -LD:\PCL\PCL1.8.1\3rdParty\FLANN\lib\
        -lflann\
        -lflann_cpp\
        -lflann_cpp_s\
        -lflann_s

LIBS += -LD:\PCL\PCL1.8.1\3rdParty\OpenNI2\Lib\
        -lOpenNI2

LIBS += -LD:\PCL\PCL1.8.1\3rdParty\Qhull\lib\
        -lqhull\
        -lqhullcpp\
        -lqhullstatic\
        -lqhullstatic_r\
        -lqhull_p\
        -lqhull_r

LIBS += -LD:\PCL\PCL1.8.1\3rdParty\VTK1\lib\
        -lvtkalglib-8.0\
        -lvtkChartsCore-8.0\
        -lvtkCommonColor-8.0\
        -lvtkCommonComputationalGeometry-8.0\
        -lvtkCommonCore-8.0\
        -lvtkCommonDataModel-8.0\
        -lvtkCommonExecutionModel-8.0\
        -lvtkCommonMath-8.0\
        -lvtkCommonMisc-8.0\
        -lvtkCommonSystem-8.0\
        -lvtkCommonTransforms-8.0\
        -lvtkDICOMParser-8.0\
        -lvtkDomainsChemistry-8.0\
        -lvtkexoIIc-8.0\
        -lvtkexpat-8.0\
        -lvtkFiltersAMR-8.0\
        -lvtkFiltersCore-8.0\
        -lvtkFiltersExtraction-8.0\
        -lvtkFiltersFlowPaths-8.0\
        -lvtkFiltersGeneral-8.0\
        -lvtkFiltersGeneric-8.0\
        -lvtkFiltersGeometry-8.0\
        -lvtkFiltersHybrid-8.0\
        -lvtkFiltersHyperTree-8.0\
        -lvtkFiltersImaging-8.0\
        -lvtkFiltersModeling-8.0\
        -lvtkFiltersParallel-8.0\
        -lvtkFiltersParallelImaging-8.0\
        -lvtkFiltersPoints-8.0\
        -lvtkFiltersProgrammable-8.0\
        -lvtkFiltersSelection-8.0\
        -lvtkFiltersSMP-8.0\
        -lvtkFiltersSources-8.0\
        -lvtkFiltersStatistics-8.0\
        -lvtkFiltersTexture-8.0\
        -lvtkFiltersTopology-8.0\
        -lvtkFiltersVerdict-8.0\
        -lvtkfreetype-8.0\
        -lvtkGeovisCore-8.0\
        -lvtkgl2ps-8.0\
        -lvtkGUISupportQt-8.0\
#        -lvtkGUISupportQtOpenGL2-8.0\
        -lvtkGUISupportQtSQL-8.0\
        -lvtkhdf5-8.0\
        -lvtkhdf5_hl-8.0\
        -lvtkImagingColor-8.0\
        -lvtkImagingCore-8.0\
        -lvtkImagingFourier-8.0\
        -lvtkImagingGeneral-8.0\
        -lvtkImagingHybrid-8.0\
        -lvtkImagingMath-8.0\
        -lvtkImagingMorphological-8.0\
        -lvtkImagingSources-8.0\
        -lvtkImagingStatistics-8.0\
        -lvtkImagingStencil-8.0\
        -lvtkInfovisCore-8.0\
        -lvtkInfovisLayout-8.0\
        -lvtkInteractionImage-8.0\
        -lvtkInteractionStyle-8.0\
        -lvtkInteractionWidgets-8.0\
        -lvtkIOAMR-8.0\
        -lvtkIOCore-8.0\
        -lvtkIOEnSight-8.0\
        -lvtkIOExodus-8.0\
        -lvtkIOExport-8.0\
        -lvtkIOExportOpenGL-8.0\
        -lvtkIOGeometry-8.0\
        -lvtkIOImage-8.0\
        -lvtkIOImport-8.0\
        -lvtkIOInfovis-8.0\
        -lvtkIOLegacy-8.0\
        -lvtkIOLSDyna-8.0\
        -lvtkIOMINC-8.0\
        -lvtkIOMovie-8.0\
        -lvtkIONetCDF-8.0\
        -lvtkIOParallel-8.0\
        -lvtkIOParallelXML-8.0\
        -lvtkIOPLY-8.0\
        -lvtkIOSQL-8.0\
        -lvtkIOTecplotTable-8.0\
        -lvtkIOVideo-8.0\
        -lvtkIOXML-8.0\
        -lvtkIOXMLParser-8.0\
        -lvtkjpeg-8.0\
        -lvtkjsoncpp-8.0\
        -lvtklibharu-8.0\
        -lvtklibxml2-8.0\
        -lvtklz4-8.0\
        -lvtkmetaio-8.0\
        -lvtkNetCDF-8.0\
        -lvtknetcdf_c++\
        -lvtkoggtheora-8.0\
        -lvtkParallelCore-8.0\
        -lvtkpng-8.0\
        -lvtkproj4-8.0\
        -lvtkRenderingAnnotation-8.0\
        -lvtkRenderingContext2D-8.0\
        -lvtkRenderingContextOpenGL2-8.0\
        -lvtkRenderingCore-8.0\
        -lvtkRenderingFreeType-8.0\
        -lvtkRenderingGL2PS-8.0\
        -lvtkRenderingGL2PSOpenGL2-8.0\
        -lvtkRenderingImage-8.0\
        -lvtkRenderingLabel-8.0\
        -lvtkRenderingLIC-8.0\
        -lvtkRenderingLOD-8.0\
        -lvtkRenderingOpenGL2-8.0\
        -lvtkRenderingQt-8.0\
        -lvtkRenderingVolume-8.0\
        -lvtkRenderingVolumeOpenGL2-8.0\
        -lvtksqlite-8.0\
        -lvtksys-8.0\
        -lvtktiff-8.0\
        -lvtkverdict-8.0\
        -lvtkViewsContext2D-8.0\
        -lvtkViewsCore-8.0\
        -lvtkViewsInfovis-8.0\
        -lvtkViewsQt-8.0\
        -lvtkzlib-8.0

LIBS += -LD:\OpenCV\opencv\build\x64\vc15\lib\
        -lopencv_world455

LIBS += -LD:\pthread\Pre-built.2\lib\x64\
        -lpthreadVC2

LIBS += -LD:\log4cpp\msvc10\x64\Release\
        -llog4cpp

}

3.3 Software interface

3.3.1 ui statement

  • Double-click the xxx.ui file

Insert image description here
Insert image description here
Insert image description here
Insert image description here
Insert image description here
Insert image description here
Insert image description here
Insert image description here

3.3.2 Button icon

Insert image description here
Insert image description here
Insert image description here
Insert image description here
Insert image description here

Insert image description here
Insert image description here
Insert image description here
Insert image description here
Insert image description here
Insert image description here

3.3.3 Other interface settings

  • I found that the writing was a bit tedious orz, so let’s quickly end the interface and talk about point cloud processing (but it did take some time to make the interface look better haha, such as borderless, zooming, mouse hover display prompts, etc. O_o)

Insert image description here

  • The following operations can be written where mainwindow is initialized.
    • Information prompted when the mouse hovers next to the buttonui->pushButton_box->setToolTip(QString("<span style=\"color: #4a90e2; font-size: 12px;\">%1</span>").arg("box"));
    • Set the button's background color to transparent ui->pushButton_box->setStyleSheet("background-color:transparent");orui->pushButton_box->setStyleSheet("background-color:rgba(0,0,0,0)");
    • Set as unfocused buttonui->pushButton_box->setFocusPolicy(Qt::NoFocus);
    • Set whether the button is availableui->pushButton_previous->setEnabled(false);
      • Some buttons need to wait until certain conditions are met before being clickable. This can reduce misoperations. For example, the previous and next point clouds cannot be clicked until the point cloud is opened (otherwise, a location that does not exist in the container will be accessed, causing an error).
    • Set background transparencysetAttribute(Qt::WA_TranslucentBackground);
    • Set borderlesssetWindowFlags(Qt::Window|Qt::FramelessWindowHint |Qt::WindowSystemMenuHint|Qt::WindowMinimizeButtonHint|Qt::WindowMaximizeButtonHint);
    • Set window background color and border arcthis->setStyleSheet("QWidget{background-color:black;border-radius:10px;}");
  • Since there are problems with window scaling and dragging after setting borderless, you can add the following code
    void resizeEvent(QResizeEvent *e);
    //由于去掉显示界面的菜单栏和标题栏,无法拖动窗口,重写关于窗口拖动用的几个函数
    void mousePressEvent(QMouseEvent *event);
    void mouseMoveEvent(QMouseEvent *event);
    void mouseReleaseEvent(QMouseEvent *event);
    void showEvent(QShowEvent* event);
void Widget::resizeEvent(QResizeEvent *e)
{
    
    
    QWidget::resizeEvent(e);
    QSize sz = e->size();
    QBitmap mask(sz);
    QPainter painter(&mask);
    painter.setRenderHint(QPainter::Antialiasing);
    painter.fillRect(0, 0, sz.width(), sz.height(), Qt::white);
    painter.setBrush(QColor(0, 0, 0));
    painter.drawRoundedRect(0, 0, sz.width(), sz.height(), 10, 10);
    setMask(mask);
}

void Widget::mousePressEvent(QMouseEvent *event)
{
    
    
    isPressedWidget = true; // 当前鼠标按下的即是QWidget而非界面上布局的其它控件
    last = event->globalPos();

//    this->setFocus();
//    if(Qt::LeftButton == event->button() && 0 == (Qt::WindowMaximized & this->windowState()))
//    {
    
    
//        QPoint temp=event->globalPos();
//        pLast=temp;    //记录鼠标按下的位置
//        event->ignore();
//    }
//    m_bPressed = true; //标记鼠标为按下状态
}

void Widget::mouseMoveEvent(QMouseEvent *event)
{
    
    
    if(this->isMaximized()) //如果当前是最大化,则不允许移动
            return;
    if (isPressedWidget)
    {
    
    
        int dx = event->globalX() - last.x();
        int dy = event->globalY() - last.y();
        last = event->globalPos();
        move(x()+dx, y()+dy);
    }
//    if(this->isMaximized()) //如果当前是最大化,则不允许移动
//            return;
//    if((event->buttons() & Qt::LeftButton) && m_bPressed)//是否左击
//    {
    
    
//        QPoint ptemp=event->globalPos();          //当前鼠标全局位置
//        ptemp=ptemp-pLast;                        //计算移动变量
//        ptemp=ptemp+pos();                        //窗口原始位置(pos()) + 鼠标移动变量(ptemp) = 最终窗口位置
//        move(ptemp);                              //移动窗口到新的位置
//    }
}

void Widget::mouseReleaseEvent(QMouseEvent *event)
{
    
    
    int dx = event->globalX() - last.x();
    int dy = event->globalY() - last.y();
    move(x()+dx, y()+dy);
    isPressedWidget = false; // 鼠标松开时,置为false

//    QApplication::restoreOverrideCursor();//恢复鼠标指针性状
//    event->ignore();
    //    m_bPressed = false;
}

void Widget::showEvent(QShowEvent *event)
{
    
    
    this->setAttribute(Qt::WA_Mapped);//解决不能及时刷新的bug
    QWidget::showEvent(event);
}

3.4 Point cloud processing

3.4.1 Point cloud reading and display

  • You can refer to the blog < Reading and displaying point clouds in .pcd/.ply/.txt/.bin/.stl format >
  • This is how you can display point clouds in Qt
    • Set the member functions of point cloud and PCLVisualizer in the class
    • pcl::PointCloudpcl::PointXYZ::Ptr cloud_;

    • boost::shared_ptrpcl::visualization::PCLVisualizer viewer_;

    • Perform the following operations when initializing the window class
cloud_.reset(new pcl::PointCloud<pcl::PointXYZ>);
viewer_.reset(new pcl::visualization::PCLVisualizer("tree&cat",false));
viewer_->setBackgroundColor(0,0,0);
ui->qvtkWidget->SetRenderWindow(viewer_->getRenderWindow());
viewer_->setupInteractor(ui->qvtkWidget->GetInteractor(),ui->qvtkWidget->GetRenderWindow());
viewer_->resetCamera();
ui->qvtkWidget->update();

3.4.2 Display the previous/next point cloud

  • int serialNum = 0;Create directory index and file name list in header fileQList<QFileInfo>* fileInfo;
  • Get getOpenFileNamethe name of the opened file using
  • /Get path name by symbol position in string
  • Set a filter to filter the file names of files with the suffix point cloud
  • Get the paths of all point clouds in the directory and store them in the file name list fileInfo
  • and iterate through the list to find the file with the same name as the currently open file to determine the index serialNum position
cloudPath_=QFileDialog::getOpenFileName(this,"pleas chose point cloud",/*""*/lastPath,
                                                   "   (*.pcd *.ply *.txt *.bin *.stl);;   (*.*)"/*,&selectedFilter,options*/);

QString temp=cloudPath_;
for(int i=temp.length();i>0;i--)
{
    
    
    if (temp[i - 1] == "/")
    {
    
    
        cloudDir=temp;
        break;
    }
    else
    {
    
    
        temp.chop(1);
    }
}

QStringList filter;
    filter<<"*.pcd"<<"*.ply"<<"*.txt"<<"*.bin"<<"*.stl";
    QDir* dir =new QDir(cloudDir);
    dir->setNameFilters(filter);
    fileInfo=new QList<QFileInfo>(dir->entryInfoList(filter));
    for (int i = 0; i < fileInfo->count(); ++i) {
    
    
        if(cloudPath_==fileInfo->at(i).filePath())
        {
    
    
            serialNum=i;
            break;
        }
    }
  • When the previous button is clicked, the index decrements. When the index <0 after decrement, set the index to list size()-1.
  • After determining that the path is not empty based on the index acquisition path, you can call readPointCloud and showPointCloud in <Blog> to read and display the point cloud .
    if(--serialNum<0)
    {
    
    
        serialNum=fileInfo->count()-1;
    }
    cloudPath_=fileInfo->at(serialNum).filePath();
    if(!cloudPath_.isEmpty())
    {
    
    
        ...
    }
  • When the next button is clicked, the index is incremented. When the index == 0 after the increment, the index is set to 0.
    if(++serialNum==fileInfo->count())
    {
    
    
        serialNum=0;
    }
    cloudPath_=fileInfo->at(serialNum).filePath();
    if(!cloudPath_.isEmpty())
    {
    
    
        ...
    }

3.4.3 Status bar displays point cloud information

  • You can add a label at the top of the interface. Each time the point cloud showPointCloud is updated, the current path name of the point cloud and point cloud and other information are displayed.
  • You can also use getMinMax3D to calculate the maximum and minimum points of the point cloud and then display it at the top to determine the range of the point cloud (you can also calculate the point cloud density, etc. for display)
pcl::getMinMax3D(*cloud,minPoint_,maxPoint_);
QString range="  ("+QString::number(minPoint_.x)+","+QString::number(minPoint_.y)+","+QString::number(minPoint_.z)+") ("+QString::number(maxPoint_.x)+","+QString::number(maxPoint_.y)+","+QString::number(maxPoint_.z)+")";
ui->label->setText(cloudPath_+QString::fromLocal8Bit("  size:")+QString::number(cloud->size())+range);

3.4.4 Point cloud processing operations

3.4.5 Thread related operations

  • You can use Qt's signals and slots mechanism
    • For example, create a new class cloudSegmentthat inherits QObject
    • cloudSegment *seg;Create a new class object pointer and QThread thread object in the window class QThread segThread_;
    • During initialization, place the pointer into the thread; connect signals and slots and start the thread
    • Exit the thread during destruction
    • (Since the sub-thread cannot operate the UI, when you need to display the point cloud of the sub-thread, you need to use signals and slots to send the point cloud of the sub-thread to the main thread for display)
//构造
seg=new cloudSegment(this);
seg->moveToThread(&segThread_);
connect(&segThread_,&QThread::finished, base, &QObject::deleteLater);
connect(this,&Widget::segcloud,seg,&cloudSegment::segCloud);
connect(seg,&cloudSegment::segDone,this,&Widget::showSegCloud);
segThread_.start();
//析构
segThread_.quit();
segThread_.wait();

3.4.6 Save point cloud

  • You can assign the interface point cloud to the member variable cloud_ each time. When clicking the save button, confirm that cloud_ is not empty and select the folder and name to save.
if(cloud_)
{
    
    
    QString filename=QFileDialog::getSaveFileName(this,tr("save point cloud"),"",tr("PointCloud (*.pcd)"));
    if(!filename.isNull())
    {
    
    
        pcl::io::savePCDFileBinary(filename.toLocal8Bit().toStdString(),*cloud_);
    }
}

3.5 Others

3.5.1 Configuration file

  • You can record the last folder path opened by writing the configuration .ini file. You can open this path directly the next time you open it without having to look for it from the initial path every time.
  • You can use QSettings to implement it, or you can write a class to operate the configuration file yourself.
//设置为类的成员函数
QSettings setting;
//窗口类初始化时初始化列表加上setting
setting("./Setting.ini", QSettings::IniFormat)
//为setting设置键值
setting.setValue("LastFilePath",cloudPath_);

3.5.2 Writing logs

3.5.3 Software release

  1. Copy the exe file generated under release to a new folder
  2. Open the compiler you use in qt. For example, mine is Qt 5.14.2 (MSVC 2017 64-bit)
  3. cd to the new folder where you save the exe and enter windeployqt name.exe (this way qt will package the required dependencies into this folder)
  4. For some external dlls, you need to copy them to the folder yourself

Insert image description here

  • The software generated in this way contains software and many other files under one file.
  • If you want to use only one file for others to use, you can use EnigmaVirtualBox to package it.

4. Software

  • What may be more practical about this update is that it adds a top status bar to display the path and number of points of the point cloud file. It is more convenient to know which point cloud is displayed and part of the point cloud information.
  • It may be the saving function, because point clouds in 5 formats can be opened. In the last save, what I saved here is the processed pcd point cloud displayed on the current interface. Even without processing, it can be saved, which is equivalent to making point clouds. Type conversion, 5 types of dump pcd
  • Other functions can be displayed by hovering the mouse near the button, such as box to draw a bounding box for the current interface point cloud, removeOuter to filter outliers, etc.
  • However, some functions I wrote in the code in order to test some functions of the project may not be applicable, such as RgnGrow area growth, plane fitting, cluster clustering, etc.

Then save the file again: D The link is still the same link as before. cloud.exe is the previous version, and treeandcat.exe is the current version. Baidu
Netdisk extraction code: 2lm2

Insert image description here

Guess you like

Origin blog.csdn.net/m0_68312479/article/details/132008580