前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【PCL】PCL点云在Qt中可视化

【PCL】PCL点云在Qt中可视化

作者头像
DevFrank
发布2024-07-24 15:04:42
680
发布2024-07-24 15:04:42
举报
文章被收录于专栏:C++开发学习交流

二进制版的vtk第三方库不支持Qt,需要重新下载vtk并用cmake编译,注意要版本对应,这里我用pcl1.8.1,对应vtk8.0,在这里下载。

编译VTK-8.0

可以参考这篇

将下载好的vtk source解压到pcl安装目录下的3rdparty,将原来的VTK备份一下,然后再源文件下创建build文件夹,编译后的文件会放在这里:

在这里插入图片描述
在这里插入图片描述

将其他文件放入src中,然后打开cmake,根据自己的配置来,点击Configure:

在这里插入图片描述
在这里插入图片描述

勾选这几项:

会这样报错,属于正常:

在这里插入图片描述
在这里插入图片描述

配置这两项后再点击Configure:

在这里插入图片描述
在这里插入图片描述

有一点要特别注意,这个Qt5_DIR一定要设置正确,否则一直出错(经验):

然后点击“Generate”生成VS项目文件。

在这里插入图片描述
在这里插入图片描述

(×备选项) 在build目录下打开终端,在VS2017编译器下,输入cmake .. -G "Visual Studio 15 2017" -A x64,会编译生成:

进入到build目录下,使用VS打开VTK.sln

首先在Debug x64下,右键ALL_BUILD生成编译,再右键INSTALL生成; 然后在Release x64下,右键ALL_BUILD生成编译,再右键INSTALL生成;(全编译生成的时间有点长,可以只生成那个QVTK模块)

将3rdParty\VTK\plugins\designer下的QVTKWidgetPlugin.dll拷贝到QT\5.12\msvc2017_64\plugins\designer下,这样Qt里面就有了QVtk的控件了。

在这里插入图片描述
在这里插入图片描述

(bug) 后来我在编译的时候一直生成不了QVTKWidgetPlugin.dll,老是报错,因为我用的Qt编译器是mingw64,不知道是不是这个的原因。(2022.11.2更新,最好用msvc编译器,不要用mingw,用msvc成功了)

在这里插入图片描述
在这里插入图片描述

至此PCL在windows下的环境已经搭配好了,可以选择重启让环境变量生效。

最后打开qt设计师,应该是可以看到QVTK这个插件的。

在这里插入图片描述
在这里插入图片描述

Qt测试demo

新建ui文件,将QVTK拖入窗体中,然后创建pclvisualizer.cpp和.h文件:

pclvisualizer.h

代码语言:javascript
复制
#ifndef PCLVISUALIZER_H	//防卫式声明
#define PCLVISUALIZER_H
 
#include <vtkAutoInit.h> 	//导入vtk必须导入,否则出错
VTK_MODULE_INIT(vtkRenderingOpenGL2);
VTK_MODULE_INIT(vtkInteractionStyle);
 
#include <QtWidgets/QMainWindow>
#include <pcl/io/pcd_io.h>	//输入输出
#include <pcl/point_types.h>	//点云类型
#include <pcl/visualization/pcl_visualizer.h>	//可视化
#include "ui_pclvisualizer.h"
 
class PCLVisualizer : public QMainWindow
{
	Q_OBJECT
public:
	PCLVisualizer(QWidget *parent = 0);	//实例化
	~PCLVisualizer();
 
private:
	Ui::PCLVisualizerClass ui;
	//点云数据存储
	pcl::PointCloud<pcl::PointXYZ>::Ptr cloud;	//实例化cloud
	boost::shared_ptr<pcl::visualization::PCLVisualizer> viewer;	//viewer
	
	//初始化vtk部件
	void initialVtkWidget();
 
private slots:
	//创建打开槽
	void onOpen();
	void exit();
	//void setcolor();
};
 
#endif // PCLVISUALIZER_H

pclvisualizer.cpp

代码语言:javascript
复制
#include <QFileDialog>
#include <iostream>
#include <vtkRenderWindow.h>	//vtk渲染
#include "pclvisualizer.h"
#include <QColorDialog>
#pragma execution_character_set("utf-8")	//编码
 
PCLVisualizer::PCLVisualizer(QWidget *parent)
	: QMainWindow(parent)
{
	ui.setupUi(this);
	//初始化
	initialVtkWidget();
	//连接信号和槽
	connect(ui.actionOpen, &QAction::triggered, this, &PCLVisualizer::onOpen);
	connect(ui.actionExit, &QAction::triggered, this, &PCLVisualizer::exit);
}
 
PCLVisualizer::~PCLVisualizer()
{
 
}

void PCLVisualizer::initialVtkWidget()
{
	cloud.reset(new pcl::PointCloud<pcl::PointXYZ>);	//reset cloud
	viewer.reset(new pcl::visualization::PCLVisualizer("viewer", false));	//reset viewer
	viewer->addPointCloud(cloud, "cloud");	//添加点云
 
	ui.qvtkWidget->SetRenderWindow(viewer->getRenderWindow());	//设置渲染
	viewer->setupInteractor(ui.qvtkWidget->GetInteractor(), ui.qvtkWidget->GetRenderWindow());	//设置交互
	ui.qvtkWidget->update();	//update
}

//读取点云数据
void PCLVisualizer::onOpen()
{
	//打开PCD文件
	QString fileName = QFileDialog::getOpenFileName(this,
		tr("Open PointCloud"), ".",
		tr("Open PCD files(*.pcd)"));
 
 	//判断是否存在
	if (!fileName.isEmpty())
	{
		std::string file_name = fileName.toStdString();
		//sensor_msgs::PointCloud2 cloud2;
		pcl::PCLPointCloud2 cloud2;
		//pcl::PointCloud<Eigen::MatrixXf> cloud2;
		Eigen::Vector4f origin;
		Eigen::Quaternionf orientation;	//四元数
		int pcd_version;
		int data_type;
		unsigned int data_idx;
		int offset = 0;
		pcl::PCDReader rd;	//实例化rd读取对象
		rd.readHeader(file_name, cloud2, origin, orientation, pcd_version, data_type, data_idx);
 
 		//判断数据类型
		if (data_type == 0)
		{
			pcl::io::loadPCDFile(fileName.toStdString(), *cloud);
		}
		else if (data_type == 2)
		{
			pcl::PCDReader reader;
			reader.read<pcl::PointXYZ>(fileName.toStdString(), *cloud);
		}
 
		viewer->updatePointCloud(cloud, "cloud");
		viewer->resetCamera();
		ui.qvtkWidget->update();
	}
}

void PCLVisualizer::exit()	//exit
{
	this->close();
}

实际上,只是把上面的代码拷贝进来就直接运行不了的,会报各种各样的错误,归根结底是PCL和VTK库编译的问题,比如编译时选择的OpenGL还是OpenGL2,有没有把VTK库的Debug和Release版本都编译一遍,VS+Qt的编译环境是Debug x64还是Release x64,所以,一直要每一步都正确,最终主要是核对这两个属性表的配置是否正确。

在这里插入图片描述
在这里插入图片描述

配置好环境后,建议先创建一个空的Qt环境,加入QVTK控件试一下是否能正常生成,如下:

在这里插入图片描述
在这里插入图片描述

我在复现的时候,还是遇到了问题,点云pcd打不开,主要是这一步的问题:

在这里插入图片描述
在这里插入图片描述

复现代码如下:

代码语言:javascript
复制
pcl_test.h
代码语言:javascript
复制
#pragma once

#include <QtWidgets/QMainWindow>

#include <QFileDialog>
#include <QColorDialog>
#include <iostream>

#include <pcl/io/pcd_io.h>	//输入输出
#include <pcl/point_types.h>	//点云类型
#include <pcl/visualization/pcl_visualizer.h>	//可视化

#include <vtkRenderWindow.h>	//vtk渲染
#include <vtkRenderer.h>
#include <vtkInteractorStyleTrackballCamera.h>
#include <vtkGenericOpenGLRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include "ui_pcl_test.h"

#include <vtkAutoInit.h> 	//导入vtk必须导入,否则出错
VTK_MODULE_INIT(vtkRenderingOpenGL2);
VTK_MODULE_INIT(vtkInteractionStyle);
VTK_MODULE_INIT(vtkRenderingFreeType);

class pcl_test : public QMainWindow
{
    Q_OBJECT

public:
    pcl_test(QWidget *parent = Q_NULLPTR);
	~pcl_test();

private:
    Ui::pcl_testClass ui;

	//点云数据存储
	pcl::PointCloud<pcl::PointXYZ>::Ptr cloud;	//实例化cloud
	boost::shared_ptr<pcl::visualization::PCLVisualizer> viewer;	//viewer
	//pcl::visualization::PCLVisualizer::Ptr viewer;

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

private slots:
	//创建打开槽
	void onOpen();
	void onExit();
	//void setcolor();
};
代码语言:javascript
复制
pcl_test.cpp
代码语言:javascript
复制
#include "pcl_test.h"
#pragma execution_character_set("utf-8")	//编码

/*
问题:addPointCloud添加点云时出错!
*/

pcl_test::pcl_test(QWidget *parent)
    : QMainWindow(parent)
{
    ui.setupUi(this);

	//初始化
	//initialVtkWidget();
	//连接信号和槽
	connect(ui.actionOpen, &QAction::triggered, this, &pcl_test::onOpen);
	connect(ui.actionExit, &QAction::triggered, this, &pcl_test::onExit);

}

pcl_test::~pcl_test()
{

}

void pcl_test::initialVtkWidget()
{
	cloud.reset(new pcl::PointCloud<pcl::PointXYZ>);	//reset cloud
	viewer.reset(new pcl::visualization::PCLVisualizer("viewer", false));	//reset viewer
	ui.qvtkWidget->SetRenderWindow(viewer->getRenderWindow());	//设置渲染

	//viewer->addPointCloud<pcl::PointXYZ>(cloud, "cloud");	//添加点云(出错)
	//viewer->setupInteractor(ui.qvtkWidget->GetInteractor(), ui.qvtkWidget->GetRenderWindow());	//设置交互
	ui.qvtkWidget->update();	//update
}

//读取点云数据
void pcl_test::onOpen()
{
	//打开PCD文件
	QString fileName = QFileDialog::getOpenFileName(this,
		tr("Open PointCloud"), ".",
		tr("Open PCD files(*.pcd)"));

	//判断是否存在
	if (!fileName.isEmpty())
	{
		std::string file_name = fileName.toStdString();
		//sensor_msgs::PointCloud2 cloud2;
		pcl::PCLPointCloud2 cloud2;
		//pcl::PointCloud<Eigen::MatrixXf> cloud2;
		Eigen::Vector4f origin;
		Eigen::Quaternionf orientation;	//四元数
		int pcd_version;
		int data_type;
		unsigned int data_idx;
		int offset = 0;
		pcl::PCDReader rd;	//实例化rd读取对象
		rd.readHeader(file_name, cloud2, origin, orientation, pcd_version, data_type, data_idx);

		//判断数据类型
		if (data_type == 0)
		{
			pcl::io::loadPCDFile(fileName.toStdString(), *cloud);
		}
		else if (data_type == 2)
		{
			pcl::PCDReader reader;
			reader.read<pcl::PointXYZ>(fileName.toStdString(), *cloud);
		}

		viewer->updatePointCloud(cloud, "cloud");
		viewer->resetCamera();
		ui.qvtkWidget->update();
	}
}

void pcl_test::onExit()	//exit
{
	this->close();
}

结果:

在这里插入图片描述
在这里插入图片描述

这两天使用下来,感觉VS+Qt+VTK太难用了,可能还是太菜吧,这个代码一直复现不出来,哪位大佬能解决的话欢迎留言。

以上。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022-11-04,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 编译VTK-8.0
  • Qt测试demo
相关产品与服务
数据保险箱
数据保险箱(Cloud Data Coffer Service,CDCS)为您提供更高安全系数的企业核心数据存储服务。您可以通过自定义过期天数的方法删除数据,避免误删带来的损害,还可以将数据跨地域存储,防止一些不可抗因素导致的数据丢失。数据保险箱支持通过控制台、API 等多样化方式快速简单接入,实现海量数据的存储管理。您可以使用数据保险箱对文件数据进行上传、下载,最终实现数据的安全存储和提取。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档