QT6.5.3 vs2022 pcl1.14.1窗体界面打开pcd点云文件

vs2022结合qt6.5.3+pcl1.14.1打开pcd文件的一个例子

提前条件:已经安装vs2022,pcl1.14.1,qt6.5.3,并且已经配置pcl属性表,其中vtk是需要编译的

Pcl1.14.1对应的是VTK9.3,编译vtk的时候要选择With_QT

vs2022中安装qt插件

设置qt路径

设置此属性为true

实例开始:打开vs2022选择QtWidgetsApplication

项目名字自定义

下一步点Finish

双击UI文件

出来设计界面后,添加一个按钮pushButton_open,设置如下图

拖动一个openGLWidget到窗体上

右键点击openGLWidget选择提升为...

提升的类名称填:QVTKOpenGLNativeWidget,下面会自动填,然后点添加

全局包含打勾,再点提升

再添加一个进度条控件,保存并闭设计窗口

回到Visual Studio中右键点击UI文件--编译(UI中修改后都需要编译)

此时运行,可能会出现以下错误

无法打开包括文件: “QOpenGLWidget”: No such file or directory QtWidgetsPcd

添加如下图位置的内容

QT += openglwidgets

重新生成

给打开按钮添加槽(事件)

添加:pushButton_openClicked()

保存后,编译

在QtWidgetsPcd.h文件中添加以下代码

#pragma once
#include <vtkAutoInit.h>
VTK_MODULE_INIT(vtkRenderingOpenGL2);
VTK_MODULE_INIT(vtkInteractionStyle);


#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
#include <pcl/visualization/pcl_visualizer.h>
    //点云数据存储
    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud;
    boost::shared_ptr<pcl::visualization::PCLVisualizer> viewer;

    //初始化vtk部件
    void initialVtkWidget();

    private slots:
        void pushButton_openClicked(); //打开pcd文件的按钮

再修改QtWidgetsPcd.cpp文件

以下是修改前的截图

修改后的代码:

#include "QtWidgetsPcd.h"

#include <QFileDialog>
#include <iostream>
#include <vtkRenderWindow.h>
#include <QColorDialog>
#include "vtkGenericOpenGLRenderWindow.h"
#include "QVTKOpenGLNativeWidget.h"
#include <QFuture>
#include <QtConcurrent/QtConcurrent>
#include <pcl/io/vtk_lib_io.h>
#include <pcl/io/ply_io.h>
#pragma execution_character_set("utf-8")


QtWidgetsPcd::QtWidgetsPcd(QWidget *parent)
    : QMainWindow(parent)
{
    ui.setupUi(this);
	initialVtkWidget();
    ui.progressBar->setValue(0); // 初始化进度条

}

QtWidgetsPcd::~QtWidgetsPcd()
{}

void QtWidgetsPcd::initialVtkWidget()
{
    cloud.reset(new pcl::PointCloud<pcl::PointXYZ>);
    auto renderer2 = vtkSmartPointer<vtkRenderer>::New();
    auto renderWindow2 = vtkSmartPointer<vtkGenericOpenGLRenderWindow>::New();
    renderWindow2->AddRenderer(renderer2);
    cloud->resize(1);
    viewer.reset(new pcl::visualization::PCLVisualizer(renderer2, renderWindow2, "viewer", false));
    viewer->addPointCloud(cloud, "cloud");

    // 添加坐标轴线条
    double lineWidth = 0.8; // 坐标轴粗细
    viewer->addLine<pcl::PointXYZ>(pcl::PointXYZ(0, 0, 0), pcl::PointXYZ(1, 0, 0), 1.0, 0.0, 0.0, "x_axis", lineWidth);
    viewer->addLine<pcl::PointXYZ>(pcl::PointXYZ(0, 0, 0), pcl::PointXYZ(0, 1, 0), 0.0, 1.0, 0.0, "y_axis", lineWidth);
    viewer->addLine<pcl::PointXYZ>(pcl::PointXYZ(0, 0, 0), pcl::PointXYZ(0, 0, 1), 0.0, 0.0, 1.0, "z_axis", lineWidth);


     //添加X, Y, Z标注
    viewer->addText3D("X", pcl::PointXYZ(1.1, 0, 0), 0.1, 1.0, 0.0, 0.0, "x_text");
    viewer->addText3D("Y", pcl::PointXYZ(0, 1.1, 0), 0.1, 0.0, 1.0, 0.0, "y_text");
    viewer->addText3D("Z", pcl::PointXYZ(0, 0, 1.1), 0.1, 0.0, 0.0, 1.0, "z_text");

    ui.openGLWidget->setRenderWindow(viewer->getRenderWindow());

    viewer->setupInteractor(ui.openGLWidget->interactor(), ui.openGLWidget->renderWindow());
    ui.openGLWidget->update();

    viewer->setBackgroundColor(0, 0, 0);
}

void QtWidgetsPcd::pushButton_openClicked()
{
    QString fileName = QFileDialog::getOpenFileName(this,
        tr("Open PointCloud"), ".",
        tr("Point Cloud Files (*.pcd *.ply *.stl)"));

    if (!fileName.isEmpty())
    {
        ui.progressBar->setValue(0); // 重置进度条

        QtConcurrent::run([this, fileName]() {
            std::string file_name = fileName.toStdString();
            std::string file_extension = file_name.substr(file_name.find_last_of('.') + 1);

            if (file_extension == "pcd")
            {
                pcl::PCDReader reader;
                reader.read(file_name, *cloud);

                // 模拟解析过程中的进度更新
                for (int i = 0; i < 100; i++)
                {
                    QThread::msleep(10); // 模拟处理延时
                    QMetaObject::invokeMethod(this, [this, i]() {
                        ui.progressBar->setValue(i + 1);
                        }, Qt::QueuedConnection);
                }
            }
            else if (file_extension == "ply")
            {
                pcl::io::loadPLYFile(file_name, *cloud);

                // 模拟解析过程中的进度更新
                for (int i = 0; i < 100; i++)
                {
                    QThread::msleep(10); // 模拟处理延时
                    QMetaObject::invokeMethod(this, [this, i]() {
                        ui.progressBar->setValue(i + 1);
                        }, Qt::QueuedConnection);
                }
            }
            else if (file_extension == "stl")
            {
                pcl::PolygonMesh mesh;
                pcl::io::loadPolygonFileSTL(file_name, mesh);
                pcl::fromPCLPointCloud2(mesh.cloud, *cloud);

                // 模拟解析过程中的进度更新
                for (int i = 0; i < 100; i++)
                {
                    QThread::msleep(10); // 模拟处理延时
                    QMetaObject::invokeMethod(this, [this, i]() {
                        ui.progressBar->setValue(i + 1);
                        }, Qt::QueuedConnection);
                }
            }

            QMetaObject::invokeMethod(this, [this]() {
                viewer->updatePointCloud(cloud, "cloud");
                viewer->resetCamera();
                viewer->getRenderWindow()->Render(); // 强制渲染
                viewer->setCameraPosition(
                    0, 0, 1,   // 相机位置 (Z轴正方向朝屏幕)
                    0, 0, 0,   // 目标点 (原点)
                    0, 1, 0    // 垂直方向 (Y轴垂直向上)
                );
                viewer->resetCamera();
                ui.openGLWidget->update();
                }, Qt::QueuedConnection);
            });
    }
}

重新生成,并运行,可以打开一个pcd文件测试

后续:

增加一个创建点云按钮 pushButton_New1

//创建点云星云
void QtWidgetsApplication3::pushButton_New1Clicked()
{
    try {
        // 创建新的RGB点云
        pcl::PointCloud<pcl::PointXYZRGB>::Ptr rgb_cloud(new pcl::PointCloud<pcl::PointXYZRGB>);
        
        // 设置点云大小
        rgb_cloud->width = 5000;
        rgb_cloud->height = 1;
        rgb_cloud->is_dense = false;
        rgb_cloud->points.resize(rgb_cloud->width * rgb_cloud->height);
        
        // 生成球面上的随机点,并为每个点设置颜色
        srand(static_cast<unsigned int>(time(0)));
        for (size_t i = 0; i < rgb_cloud->points.size(); ++i)
        {
            // 生成球面坐标
            double theta = ((double)rand() / RAND_MAX) * 2.0 * M_PI;  // 0 到 2π
            double phi = acos(1 - 2 * ((double)rand() / RAND_MAX));   // 0 到 π
            double radius = 5.0;
            
            // 设置位置
            rgb_cloud->points[i].x = radius * sin(phi) * cos(theta);
            rgb_cloud->points[i].y = radius * sin(phi) * sin(theta);
            rgb_cloud->points[i].z = radius * cos(phi);
            
            // 基于位置设置渐变色
            // 将球面坐标映射到RGB颜色空间
            uint8_t r = static_cast<uint8_t>((sin(theta) + 1) * 127.5);
            uint8_t g = static_cast<uint8_t>((cos(phi) + 1) * 127.5);
            uint8_t b = static_cast<uint8_t>((cos(theta) + 1) * 127.5);
            
            // 设置点的RGB颜色
            rgb_cloud->points[i].r = r;
            rgb_cloud->points[i].g = g;
            rgb_cloud->points[i].b = b;
        }
        
        // 转换为XYZ点云以供显示
        pcl::copyPointCloud(*rgb_cloud, *cloud);
        
        // 移除旧的点云
        viewer->removePointCloud("cloud");
        
        // 使用RGB颜色处理器
        pcl::visualization::PointCloudColorHandlerRGBField<pcl::PointXYZRGB> rgb(rgb_cloud);
        viewer->addPointCloud<pcl::PointXYZRGB>(rgb_cloud, rgb, "cloud");
        
        // 设置点云渲染属性
        viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 3, "cloud");
        
        // 设置相机位置
        viewer->setCameraPosition(
            15, 15, 15,  // 相机位置
            0, 0, 0,     // 目标点
            0, 0, 1      // 上方向
        );
        
        // 重置相机和更新显示
        viewer->resetCamera();
        viewer->getRenderWindow()->Render();
        ui.openGLWidget->update();
        
        std::cout << "彩色点云生成成功!" << std::endl;
        
    } catch (const std::exception& e) {
        std::cerr << "生成点云时发生错误: " << e.what() << std::endl;
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

养牛大人

感谢您的鼓励!

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

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

打赏作者

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

抵扣说明:

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

余额充值