VS+Qt+C++点云PCL三维显示编辑系统

程序示例精选
VS+Qt+C++点云PCL三维显示编辑系统
如需安装运行环境或远程调试,见文章底部个人QQ名片,由专业技术人员远程协助!

前言

这篇博客针对《VS+Qt+C++点云PCL三维显示编辑系统》编写代码,代码整洁,规则,易读。 学习与应用推荐首选。


文章目录

一、所需工具软件
二、使用步骤
       1. 主要代码
       2. 运行结果
三、在线协助

一、所需工具软件

       1. VS2019,Qt
       2. C++

二、使用步骤

代码如下(示例):

#include "PointCloudVision.h"
#include <QFileDialog>
#include <QFile>
#include <QMessageBox>
#include <QColorDialog>

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

	//初始化
	init();
}

//获取两个点平行于坐标轴的最短距离
double getMinValue(PointT p1, PointT p2);

//获取两个点平行于坐标轴的最长距离
double getMaxValue(PointT p1, PointT p2);

//初始化
void PointCloudVision::init()
{
	//点云初始化
	m_currentCloud.reset(new PointCloudT);

	//可视化对象初始化
	viewer.reset(new pcl::visualization::PCLVisualizer("viewer", false));

	viewer->addPointCloud(m_currentCloud, "cloud");

	//设置VTK可视化窗口指针
	ui.qvtkWidget->SetRenderWindow(viewer->getRenderWindow());

	//设置窗口交互,窗口可接受键盘等事件
	viewer->setupInteractor(ui.qvtkWidget->GetInteractor(), ui.qvtkWidget->GetRenderWindow());

	//添加坐标轴
	viewer->addCoordinateSystem();

	//ui.qvtkWidget->update();

	//槽函数
	connect(&heightRampDlg, SIGNAL(setHeightRamp(int, double)), this, SLOT(setHeightRamp(int, double)));


}

//打开点云
void PointCloudVision::on_action_open_triggered()
{
	init();

	QString fileName = QFileDialog::getOpenFileName(this, "Open PointCloud", ".", "Open PCD files(*.pcd)");
	if (!fileName.isEmpty())
	{
		std::string file_name = fileName.toStdString();

		pcl::PCLPointCloud2 cloud2;
		Eigen::Vector4f origin;
		Eigen::Quaternionf orientation;
		int pcd_version;
		int data_type;
		unsigned int data_idx;
		int offset = 0;
		pcl::PCDReader rd;
		rd.readHeader(file_name, cloud2, origin, orientation, pcd_version, data_type, data_idx);
		if (data_type == 0)
		{
			pcl::io::loadPCDFile(fileName.toStdString(), *m_currentCloud);
		}
		else if (data_type == 2)
		{
			pcl::PCDReader reader;
			reader.read<pcl::PointXYZ>(fileName.toStdString(), *m_currentCloud);
		}

		viewer->addCoordinateSystem();

		viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 3, "cloud");
		viewer->updatePointCloud(m_currentCloud, "cloud");

		// 获取点云数据的最小和最大坐标值
		pcl::getMinMax3D(*m_currentCloud, p_min, p_max);

		viewer->resetCamera();
		ui.qvtkWidget->update();
	}
}

//重设视角
void PointCloudVision::on_action_reset_triggered()
{
	if (!m_currentCloud->empty())
	{
		viewer->resetCamera();
		ui.qvtkWidget->update();
	}
}

//俯视图
void PointCloudVision::on_action_up_triggered()
{
	if (!m_currentCloud->empty())
	{
		viewer->setCameraPosition(0.5 * (p_min.x + p_max.x), 0.5 * (p_min.y + p_max.y), p_max.z + 2 * maxLen, 0.5 * (p_min.x + p_max.x), 0.5 * (p_min.y + p_max.y), 0, 0, 1, 0);
		viewer->updatePointCloud(m_currentCloud, "cloud");
		ui.qvtkWidget->update();

		on_action_reset_triggered();
	}
}

//前视图
void PointCloudVision::on_action_front_triggered()
{
	if (!m_currentCloud->empty())
	{
		viewer->setCameraPosition(0.5 * (p_min.x + p_max.x), p_min.y - 2 * maxLen, 0.5 * (p_min.z + p_max.z), 0.5 * (p_min.x + p_max.x), 0, 0.5 * (p_min.z + p_max.z), 0, 0, 1);
		viewer->updatePointCloud(m_currentCloud, "cloud");
		ui.qvtkWidget->update();

		on_action_reset_triggered();
	}
}

//左视图
void PointCloudVision::on_action_left_triggered()
{
	if (!m_currentCloud->empty())
	{
		viewer->setCameraPosition(p_min.x - 2 * maxLen, 0.5 * (p_min.y + p_max.y), 0.5 * (p_min.z + p_max.z), 0, 0.5 * (p_min.y + p_max.y), 0.5 * (p_min.z + p_max.z), 0, 0, 1);
		viewer->updatePointCloud(m_currentCloud, "cloud");
		ui.qvtkWidget->update();

		on_action_reset_triggered();
	}
}

//后视图
void PointCloudVision::on_action_back_triggered()
{
	if (!m_currentCloud->empty())
	{
		viewer->setCameraPosition(0.5 * (p_min.x + p_max.x), p_max.y + 2 * maxLen, 0.5 * (p_min.z + p_max.z), 0.5 * (p_min.x + p_max.x), 0, 0.5 * (p_min.z + p_max.z), 0, 0, 1);
		viewer->updatePointCloud(m_currentCloud, "cloud");
		ui.qvtkWidget->update();

		on_action_reset_triggered();
	}
}

//右视图
void PointCloudVision::on_action_right_triggered()
{
	if (!m_currentCloud->empty())
	{
		viewer->setCameraPosition(p_max.x + 2 * maxLen, 0.5 * (p_min.y + p_max.y), 0.5 * (p_min.z + p_max.z), 0, 0.5 * (p_min.y + p_max.y), 0.5 * (p_min.z + p_max.z), 0, 0, 1);
		viewer->updatePointCloud(m_currentCloud, "cloud");
		ui.qvtkWidget->update();

		on_action_reset_triggered();
	}
}

//底视图
void PointCloudVision::on_action_bottom_triggered()
{
	if (!m_currentCloud->empty())
	{
		viewer->setCameraPosition(0.5 * (p_min.x + p_max.x), 0.5 * (p_min.y + p_max.y), p_min.z - 2 * maxLen, 0.5 * (p_min.x + p_max.x), 0.5 * (p_min.y + p_max.y), 0, 0, 1, 0);
		viewer->updatePointCloud(m_currentCloud, "cloud");
		ui.qvtkWidget->update();

		on_action_reset_triggered();
	}
}

//前轴测
void PointCloudVision::on_action_frontIso_triggered()
{
	if (!m_currentCloud->empty())
	{
		viewer->setCameraPosition(p_min.x - 2 * maxLen, p_min.y - 2 * maxLen, p_max.z + 2 * maxLen, 0.5 * (p_min.x + p_max.x), 0.5 * (p_min.y + p_max.y), 0.5 * (p_min.z + p_max.z), 1, 1, 0);
		viewer->updatePointCloud(m_currentCloud, "cloud");
		ui.qvtkWidget->update();

		on_action_reset_triggered();
	}
}

//后轴测
void PointCloudVision::on_action_backIso_triggered()
{
	viewer->setCameraPosition(p_max.x + 2 * maxLen, p_max.y + 2 * maxLen, p_max.z + 2 * maxLen, 0.5 * (p_min.x + p_max.x), 0.5 * (p_min.y + p_max.y), 0.5 * (p_min.z + p_max.z), -1, -1, 0);
	viewer->updatePointCloud(m_currentCloud, "cloud");
	ui.qvtkWidget->update();

	on_action_reset_triggered();
}

//设置点云颜色
void PointCloudVision::on_action_setColor_triggered()
{
	QColor color = QColorDialog::getColor(Qt::white, this, "设置点云颜色", QColorDialog::ShowAlphaChannel);

	viewer->removeAllPointClouds();
	pcl::visualization::PointCloudColorHandlerCustom<PointT> singleColor(m_currentCloud, color.red(), color.green(), color.blue());
	viewer->addPointCloud(m_currentCloud, singleColor, "myCloud", 0);
	viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_OPACITY, color.alpha() * 1.0 / 255, "myCloud");

	ui.qvtkWidget->update();

}

//设置高度渲染
void PointCloudVision::on_action_heightRamp_triggered()
{
	heightRampDlg.show();
}

//进行高度渲染
void PointCloudVision::setHeightRamp(int dir, double height)
{
	//清空点云
	viewer->removeAllPointClouds();
	m_heightCloudList.clear();

	double min_range = 0;
	double max_range = 0;
	std::string field = "x";

	switch (dir)
	{
	case 0:
		min_range = p_min.x;
		max_range = p_max.x;
		field = "x";
		break;

	case 1:
		min_range = p_min.y;
		max_range = p_max.y;
		field = "y";
		break;

	case 2:
		min_range = p_min.z;
		max_range = p_max.z;
		field = "z";
		break;
	default:
		break;
	}

	for (double i = min_range - 1; i < max_range + height;)
	{
		PointCloudT::Ptr cloudTemp(new PointCloudT());

		pcl::PassThrough<PointT> pass;			//直通滤波器对象
		pass.setInputCloud(m_currentCloud);		//输入点云
		pass.setFilterFieldName(field);			//设置过滤字段
		pass.setFilterLimits(i, i + height);	//设置过滤范围
		pass.setFilterLimitsNegative(false);	//设置保留字段
		pass.filter(*cloudTemp);				//执行滤波

		i += height;

		m_heightCloudList.append(cloudTemp);
	}

	//分段渲染
	for (int j = 0; j < m_heightCloudList.size(); j++)
	{
		pcl::visualization::PointCloudColorHandlerGenericField<PointT> fieldColor(m_heightCloudList.at(j), field);
		std::string index = std::to_string(j);
		viewer->addPointCloud(m_heightCloudList.at(j), fieldColor, index);
	}

}

double getMinValue(PointT p1, PointT p2)
{
	double min = 0;

	if (p1.x - p2.x > p1.y - p2.y)
	{
		min = p1.y - p2.y;
	}
	else
	{
		min = p1.x - p2.x;
	}

	if (min > p1.z - p2.z)
	{
		min = p1.z - p2.z;
	}

	return min;
}


double getMaxValue(PointT p1, PointT p2)
{
	double max = 0;

	if (p1.x - p2.x > p1.y - p2.y)
	{
		max = p1.x - p2.x;
	}
	else
	{
		max = p1.y - p2.y;
	}

	if (max < p1.z - p2.z)
	{
		max = p1.z - p2.z;
	}

	return max;
}


运行结果

三、在线协助:

如需安装运行环境或远程调试,见文章底部个人 QQ 名片,由专业技术人员远程协助!

1)远程安装运行环境,代码调试
2)Visual Studio, Qt, C++, Python编程语言入门指导
3)界面美化
4)软件制作
5)云服务器申请
6)网站制作

当前文章连接:https://blog.csdn.net/alicema1111/article/details/132666851
个人博客主页https://blog.csdn.net/alicema1111?type=blog
博主所有文章点这里:https://blog.csdn.net/alicema1111?type=blog

博主推荐:
Python人脸识别考勤打卡系统:
https://blog.csdn.net/alicema1111/article/details/133434445
Python果树水果识别https://blog.csdn.net/alicema1111/article/details/130862842
Python+Yolov8+Deepsort入口人流量统计:https://blog.csdn.net/alicema1111/article/details/130454430
Python+Qt人脸识别门禁管理系统:https://blog.csdn.net/alicema1111/article/details/130353433
Python+Qt指纹录入识别考勤系统:https://blog.csdn.net/alicema1111/article/details/129338432
Python Yolov5火焰烟雾识别源码分享:https://blog.csdn.net/alicema1111/article/details/128420453
Python+Yolov8路面桥梁墙体裂缝识别:https://blog.csdn.net/alicema1111/article/details/133434445
Python+Yolov5道路障碍物识别:https://blog.csdn.net/alicema1111/article/details/129589741
Python+Yolov5跌倒检测 摔倒检测 人物目标行为 人体特征识别:https://blog.csdn.net/alicema1111/article/details/129272048

  • 20
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

荷塘月色2

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

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

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

打赏作者

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

抵扣说明:

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

余额充值