【PCL】PCLVisualizer 显示

1. 相关说明

2. CMakeLists.txt

# 指定最低的CMAKE版本
CMAKE_MINIMUM_REQUIRED(VERSION 3.22 FATAL_ERROR)

# 创建项目
PROJECT(PCLSamples LANGUAGES CXX)

# 指定CPLUSPLUS标准
SET(CMAKE_CXX_STANDARD_REQUIRED ON)
SET(CMAKE_CXX_STANDARD 14)
SET(CMAKE_C_STANDARD 14)
SET(CMAKE_C_STANDARD_REQUIRED ON)

# 查找第三方依赖库
FIND_PACKAGE(PCL 1.11 REQUIRED)

# 添加可执行文件
ADD_EXECUTABLE(PCLSample src/main.cpp)

# 添加头文件目录
TARGET_INCLUDE_DIRECTORIES(PCLSample PRIVATE ${PCL_INCLUDE_DIRS})

# 添加库目录
TARGET_LINK_DIRECTORIES(PCLSample PRIVATE ${PCL_LIBRARY_DIRS})

# 添加编译器定义
TARGET_COMPILE_DEFINITIONS(PCLSample PRIVATE ${PCL_DEFINITIONS})
# 取消已有的编译器定义
#SET_TARGET_PROPERTIES(PCLSample PROPERTIES COMPILE_FLAGS "/UBOOST_ALL_NO_LIB-DBOOST_ALL_NO_LIB")

# 添加依赖库文件
target_link_libraries(PCLSample PRIVATE ${PCL_LIBRARIES})

3. main.cpp

#include <iostream>                           // C++标准输入输出流
#include <thread>                             // C++标准线程头文件
#include <pcl/common/angles.h>                // PCL角度转换相关函数
#include <pcl/features/normal_3d.h>           // 3D 法线相关特征
#include <pcl/visualization/pcl_visualizer.h> // PCL可视化头文件
#include <pcl/console/parse.h>                // PCL命令行参数解析

using namespace std::chrono_literals;
/***********************************************************************************************************************
 * 全局参数
 **********************************************************************************************************************/
 /// 打印帮助信息
 /// \param programName 程序名称
void printHelper(const char *programName)
{
    std::cout << "\n\nUsage: " << programName << " [options]\n\n"
              << "Options:\n"
              << "-------------------------------------------\n"
              << "-h           this help\n"
              << "-s           Simple visualisation example\n"
              << "-r           RGB colour visualisation example\n"
              << "-c           Custom colour visualisation example\n"
              << "-n           Normals visualisation example\n"
              << "-a           Shapes visualisation example\n"
              << "-v           Viewports example\n"
              << "-i           Interaction Customization example\n"
              << "\n\n";
}

/// 显示 PointXYZ 类型
/// \param cloud 点云数据
/// \return
pcl::visualization::PCLVisualizer::Ptr viewXyz(const pcl::PointCloud<pcl::PointXYZ>::ConstPtr cloud)
{
    pcl::visualization::PCLVisualizer::Ptr viewer(new pcl::visualization::PCLVisualizer("3D Viewer"));
    viewer->setBackgroundColor(0, 0, 0);
    viewer->addPointCloud<pcl::PointXYZ>(cloud, "sample cloud");
    /*
     * PCL_VISUALIZER_POINT_SIZE,   // 点尺寸(整型), [1, ∝)
     * PCL_VISUALIZER_OPACITY,      // 透明度 [0.0-1.0]
     * PCL_VISUALIZER_LINE_WIDTH ,  // 线宽 (整型), [1, ∝)
     * PCL_VISUALIZER_FONT_SIZE,    // 字体大小
     * PCL_VISUALIZER_COLOR,        // 显示颜色RGB[0.0-1.0]
     * PCL_VISUALIZER_REPRESENTATION,
     * PCL_VISUALIZER_IMMEDIATE_RENDERING,
     * PCL_VISUALIZER_SHADING,
     * PCL_VISUALIZER_LUT,
     * PCL_VISUALIZER_LUT_RANGE
     */
    viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 1, "sample cloud");
    viewer->addCoordinateSystem(1.0);
    viewer->initCameraParameters();
    return (viewer);
}

/// 显示 PointXYZRGB 类型
/// \param cloud 点云数据
/// \return
pcl::visualization::PCLVisualizer::Ptr viewRgb(const pcl::PointCloud<pcl::PointXYZRGB>::ConstPtr cloud)
{
    pcl::visualization::PCLVisualizer::Ptr viewer(new pcl::visualization::PCLVisualizer("3D Viewer"));
    viewer->setBackgroundColor(0, 0, 0);
    // 构建点云数据自带颜色
    pcl::visualization::PointCloudColorHandlerRGBField<pcl::PointXYZRGB> rgb(cloud);
    viewer->addPointCloud<pcl::PointXYZRGB>(cloud, rgb, "sample cloud");
    viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 3, "sample cloud");
    viewer->addCoordinateSystem(1.0);
    viewer->initCameraParameters();
    return (viewer);
}

/// 显示 PointXYZ + 附加自定义颜色
/// \param cloud 点云数据
/// \return
pcl::visualization::PCLVisualizer::Ptr viewCustomColor(const pcl::PointCloud<pcl::PointXYZ>::ConstPtr cloud)
{
    pcl::visualization::PCLVisualizer::Ptr viewer(new pcl::visualization::PCLVisualizer("3D Viewer"));
    viewer->setBackgroundColor(0, 0, 0);
    // 使用自定义颜色渲染器
    pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> single_color(cloud, 0, 255, 0);
    viewer->addPointCloud<pcl::PointXYZ>(cloud, single_color, "sample cloud");
    viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 3, "sample cloud");
    viewer->addCoordinateSystem(1.0);
    viewer->initCameraParameters();
    return (viewer);
}

/// 显示点云 + 法线
/// \param cloud 点云
/// \param normals 法线
/// \return
pcl::visualization::PCLVisualizer::Ptr viewNormal(const pcl::PointCloud<pcl::PointXYZRGB>::ConstPtr cloud,
                                                  const pcl::PointCloud<pcl::Normal>::ConstPtr normals)
{
    pcl::visualization::PCLVisualizer::Ptr viewer(new pcl::visualization::PCLVisualizer("3D Viewer"));
    viewer->setBackgroundColor(0, 0, 0);
    // 点云颜色信息
    pcl::visualization::PointCloudColorHandlerRGBField<pcl::PointXYZRGB> rgb(cloud);
    // 添加点云
    viewer->addPointCloud<pcl::PointXYZRGB>(cloud, rgb, "sample cloud");
    viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 3, "sample cloud");
    // 添加法线
    viewer->addPointCloudNormals<pcl::PointXYZRGB, pcl::Normal>(cloud, normals, 10, 0.05, "normals");
    viewer->addCoordinateSystem(1.0);
    viewer->initCameraParameters();
    return (viewer);
}

/// 显示形状
/// \param cloud 点云
/// \return
pcl::visualization::PCLVisualizer::Ptr viewShape(const pcl::PointCloud<pcl::PointXYZRGB>::ConstPtr cloud)
{
    pcl::visualization::PCLVisualizer::Ptr viewer(new pcl::visualization::PCLVisualizer("3D Viewer"));
    viewer->setBackgroundColor(0, 0, 0);

    pcl::visualization::PointCloudColorHandlerRGBField<pcl::PointXYZRGB> rgb(cloud);
    viewer->addPointCloud<pcl::PointXYZRGB>(cloud, rgb, "sample cloud");
    viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 3, "sample cloud");

    viewer->addCoordinateSystem(1.0);
    viewer->initCameraParameters();

    // 画线
    viewer->addLine<pcl::PointXYZRGB>((*cloud)[0], (*cloud)[cloud->size() - 1], "line");
    // 画球
    viewer->addSphere((*cloud)[0], 0.2, 0.5, 0.5, 0.0, "sphere");

    // 平面
    pcl::ModelCoefficients coefficients;
    coefficients.values.push_back(0.0);
    coefficients.values.push_back(0.0);
    coefficients.values.push_back(1.0);
    coefficients.values.push_back(0.0);
    viewer->addPlane(coefficients, "plane");

    // 圆锥
    coefficients.values.clear();
    coefficients.values.push_back(0.3);
    coefficients.values.push_back(0.3);
    coefficients.values.push_back(0.0);
    coefficients.values.push_back(0.0);
    coefficients.values.push_back(1.0);
    coefficients.values.push_back(0.0);
    coefficients.values.push_back(5.0);
    viewer->addCone(coefficients, "cone");

    return (viewer);
}

/// 多视图显示
/// \param cloud 点云
/// \param normals1 法线一
/// \param normals2 法线二
/// \return
pcl::visualization::PCLVisualizer::Ptr multiViews(const pcl::PointCloud<pcl::PointXYZRGB>::ConstPtr cloud,
                                                  const pcl::PointCloud<pcl::Normal>::ConstPtr normals1,
                                                  const pcl::PointCloud<pcl::Normal>::ConstPtr normals2)
{
    pcl::visualization::PCLVisualizer::Ptr viewer(new pcl::visualization::PCLVisualizer("3D Viewer"));
    viewer->initCameraParameters();

    // 视图一
    int v1(0);
    viewer->createViewPort(0.0, 0.0, 0.5, 1.0, v1);
    viewer->setBackgroundColor(0, 0, 0, v1);
    viewer->addText("Radius: 0.01", 10, 10, "v1 text", v1);
    pcl::visualization::PointCloudColorHandlerRGBField<pcl::PointXYZRGB> rgb(cloud);
    viewer->addPointCloud<pcl::PointXYZRGB>(cloud, rgb, "sample cloud1", v1);

    // 视图二
    int v2(0);
    viewer->createViewPort(0.5, 0.0, 1.0, 1.0, v2);
    viewer->setBackgroundColor(0.3, 0.3, 0.3, v2);
    viewer->addText("Radius: 0.1", 10, 10, "v2 text", v2);
    pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZRGB> single_color(cloud, 0, 255, 0);
    viewer->addPointCloud<pcl::PointXYZRGB>(cloud, single_color, "sample cloud2", v2);

    viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 3, "sample cloud1");
    viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 3, "sample cloud2");
    viewer->addCoordinateSystem(1.0);

    viewer->addPointCloudNormals<pcl::PointXYZRGB, pcl::Normal>(cloud, normals1, 10, 0.05, "normals1", v1);
    viewer->addPointCloudNormals<pcl::PointXYZRGB, pcl::Normal>(cloud, normals2, 10, 0.05, "normals2", v2);

    return (viewer);
}

unsigned int text_id = 0;
/// 键盘事件
/// \param event 事件
/// \param viewer_void 事件参数
void keyboardEventOccurred(const pcl::visualization::KeyboardEvent &event, void *viewer_void)
{
    auto *viewer = static_cast<pcl::visualization::PCLVisualizer *>(viewer_void);
    if (event.getKeySym() == "r" && event.keyDown())
    {
        std::cout << "r was pressed => removing all text" << std::endl;

        char str[512];
        for (unsigned int i = 0; i < text_id; ++i)
        {
            sprintf(str, "text#%03d", i);
            viewer->removeShape(str);
        }
        text_id = 0;
    }
}

/// 鼠标事件
/// \param event 事件
/// \param viewer_void 事件参数
void mouseEventOccurred(const pcl::visualization::MouseEvent &event, void *viewer_void)
{
    auto *viewer = static_cast<pcl::visualization::PCLVisualizer *>(viewer_void);
    if (event.getButton() == pcl::visualization::MouseEvent::LeftButton &&
        event.getType() == pcl::visualization::MouseEvent::MouseButtonRelease)
    {
        std::cout << "Left mouse button released at position (" << event.getX() << ", " << event.getY() << ")" << std::endl;

        char str[512];
        sprintf(str, "text#%03d", text_id++);
        viewer->addText("clicked here", event.getX(), event.getY(), str);
    }
}

/// 键盘 + 鼠标回调函数
/// \return
pcl::visualization::PCLVisualizer::Ptr interactionCustomizationVis()
{
    pcl::visualization::PCLVisualizer::Ptr viewer(new pcl::visualization::PCLVisualizer("3D Viewer"));
    viewer->setBackgroundColor(0, 0, 0);
    viewer->addCoordinateSystem(1.0);

    viewer->registerKeyboardCallback(keyboardEventOccurred, (void *)viewer.get());
    viewer->registerMouseCallback(mouseEventOccurred, (void *)viewer.get());

    return (viewer);
}

/***********************************************************************************************************************
 * 主函数调用
 **********************************************************************************************************************/
int main(int argc, char **argv)
{
    bool simple(false);
    bool rgb(false);
    bool custom_c(false);
    bool normals(false);
    bool shapes(false);
    bool viewports(false);
    bool interaction_customization(false);

    /*******************************************************************************************************************
     * 参数解析
     ******************************************************************************************************************/
    // 查看命令行参数中是否存在 -h 选项,如果存在打印使用帮助信息
    if (pcl::console::find_argument(argc, argv, "-h") >= 0)
    {
        printHelper(argv[0]);
        return EXIT_FAILURE;
    }
    else if (pcl::console::find_argument(argc, argv, "-s") >= 0)
    {
        simple = true;
        std::cout << "Simple visualisation example\n";
    }
    else if (pcl::console::find_argument(argc, argv, "-c") >= 0)
    {
        custom_c = true;
        std::cout << "Custom colour visualisation example\n";
    }
    else if (pcl::console::find_argument(argc, argv, "-r") >= 0)
    {
        rgb = true;
        std::cout << "RGB colour visualisation example\n";
    }
    else if (pcl::console::find_argument(argc, argv, "-n") >= 0)
    {
        normals = true;
        std::cout << "Normals visualisation example\n";
    }
    else if (pcl::console::find_argument(argc, argv, "-a") >= 0)
    {
        shapes = true;
        std::cout << "Shapes visualisation example\n";
    }
    else if (pcl::console::find_argument(argc, argv, "-v") >= 0)
    {
        viewports = true;
        std::cout << "Viewports example\n";
    }
    else if (pcl::console::find_argument(argc, argv, "-i") >= 0)
    {
        interaction_customization = true;
        std::cout << "Interaction Customization example\n";
    }
    else
    {
        printHelper(argv[0]);
        return 0;
    }

    /*******************************************************************************************************************
     * 创建点云
     ******************************************************************************************************************/
    // 定义 PointXYZ 类型智能指针对象
    pcl::PointCloud<pcl::PointXYZ>::Ptr xyzCloudPtr(new pcl::PointCloud<pcl::PointXYZ>);

    // 定义 PointXYZEGB 类型智能指针对象
    pcl::PointCloud<pcl::PointXYZRGB>::Ptr rgbCloudPtr(new pcl::PointCloud<pcl::PointXYZRGB>);

    // 创建一个沿着Z轴方向椭圆型柱面点云,对于PointXYZRGB类型,颜色逐步从红到绿再到蓝
    std::uint8_t r(255), g(15), b(15);
    for (float z(-1.0); z <= 1.0; z += 0.05)
    {
        for (float angle(0.0); angle <= 360.0; angle += 5.0)
        {
            pcl::PointXYZ xyzPoint;
            xyzPoint.x = 0.5f * std::cosf(pcl::deg2rad(angle));
            xyzPoint.y = 1.0f * std::sinf(pcl::deg2rad(angle));
            xyzPoint.z = z;
            xyzCloudPtr->points.push_back(xyzPoint);

            pcl::PointXYZRGB point(xyzPoint.x, xyzPoint.y, xyzPoint.z, r, g, b);
            rgbCloudPtr->points.push_back(point);
        }

        if (z < 0.0)
        {
            r -= 12;
            g += 12;
        }
        else
        {
            g -= 12;
            b += 12;
        }
    }
    xyzCloudPtr->width = xyzCloudPtr->size();
    xyzCloudPtr->height = 1;

    rgbCloudPtr->width = rgbCloudPtr->size();
    rgbCloudPtr->height = 1;

    /*******************************************************************************************************************
     * 计算点云法线(搜索半径 0.01)
     ******************************************************************************************************************/
    pcl::NormalEstimation<pcl::PointXYZRGB, pcl::Normal> ne;
    ne.setInputCloud(rgbCloudPtr);
    pcl::search::KdTree<pcl::PointXYZRGB>::Ptr tree(new pcl::search::KdTree<pcl::PointXYZRGB>());
    ne.setSearchMethod(tree);
    pcl::PointCloud<pcl::Normal>::Ptr rgbCloudNormal(new pcl::PointCloud<pcl::Normal>);
    ne.setRadiusSearch(0.05);
    ne.compute(*rgbCloudNormal);

    /*******************************************************************************************************************
     * 计算点云法线(搜索半径 0.1)
     ******************************************************************************************************************/
    pcl::PointCloud<pcl::Normal>::Ptr xyzCloudNormal(new pcl::PointCloud<pcl::Normal>);
    ne.setRadiusSearch(0.1);
    ne.compute(*xyzCloudNormal);

    pcl::visualization::PCLVisualizer::Ptr viewer;
    if (simple)
        viewer = viewXyz(xyzCloudPtr);
    else if (rgb)
        viewer = viewRgb(rgbCloudPtr);
    else if (custom_c)
        viewer = viewCustomColor(xyzCloudPtr);
    else if (normals)
        viewer = viewNormal(rgbCloudPtr, rgbCloudNormal);
    else if (shapes)
        viewer = viewShape(rgbCloudPtr);
    else if (viewports)
        viewer = multiViews(rgbCloudPtr, rgbCloudNormal, xyzCloudNormal);
    else if (interaction_customization)
        viewer = interactionCustomizationVis();

    /*******************************************************************************************************************
     * 显示循环
     ******************************************************************************************************************/
    while (!viewer->wasStopped())
    {
        viewer->spinOnce(100);
        std::this_thread::sleep_for(100ms);
    }
}

4. 效果图

4.1 PointXYZ

在这里插入图片描述

4.2 PointXYZRGB 自带颜色数据

在这里插入图片描述

4.3 PointXYZ 附加颜色

在这里插入图片描述

4.4 法线

在这里插入图片描述

4.5 显示形状

在这里插入图片描述

4.6 多视图

在这里插入图片描述

4.7 鼠标键盘事件

  • 鼠标事件
    在这里插入图片描述
  • 键盘事件(按下R键,清空当前显示)
    在这里插入图片描述
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

zhy29563

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值