当前位置: 首页 > news >正文

VTK9.2.0+Qt5.14.0 绘制点云

背景

为了显示结构光重建后的点云,开发QT5.14.0+VTK9.2.0的上位机软件,用于对结构光3D相机进行控制,并接收传输回来的3D数据,显示在窗口中。

配置QT和VTK

VTK9.2.0下载源码,用Cmake编译,编译好的VTK9.2.0-vs2017在链接中:VTK9.2.0-vs2017编译工程

QT5.14.0下载链接
在这里插入图片描述

VTK绘制点云

VTK构造显示数据的基本流程是:
Point -> Cell -> Poly -> PolyMapper -> Actor -> Renderer -> QVTKOpenGLNativeWidget
其中,
⋅ \cdot vtkPoints类对应创建点数据,包含点的坐标,以及属性
⋅ \cdot vtkCellArray类是构造一种元素,比如三角网格,对应有三个point,那么一个cell中就会存储这三个point的索引值
⋅ \cdot vtkPolyData类是构造多边形元素
⋅ \cdot vtkActor类是构造“演员”
⋅ \cdot vtkRenderer类是构造着色器,理解为渲染场景的控制,包含“演员”、光源、背景等
⋅ \cdot vtkPolyDataMapper类将多边形元素和Actor建立联系
⋅ \cdot QVTKOpenGLNativeWidget类是渲染窗口控件
在qt中创建VTK渲染窗口控件有两种方式:
① 双击工程左侧.ui文件,在qt designer中创建ui.openGLWidget对象
在这里插入图片描述
ui.openGLWidget是通过qt designer,拖入QVTKWidget控件,右键该控件选择“提升窗口部件”,基类选择QOpenGLWidget, 提升的类名称为QVTKOpenGLNativeWidget, 在右上角的对象查看器中,重命名为openGLWidget. (注意:VTK8的创建方式是不一样的,注意版本)

在这里插入图片描述
② 方法二是直接用代码生成的方式,在工程的构造函数中直接new一个QVTKOpenGLNativeWidget对象,并设置其位置信息

QVtkDemo2::QVtkDemo2(QWidget *parent): QMainWindow(parent)
{ui.setupUi(this);//new一个QVTKOpenGLNativeWidget的对象ui.openGLWidget = new QVTKOpenGLNativeWidget(this);//设置渲染窗口的尺寸ui.openGLWidget->resize(100, 100); //设置左上角的在主窗口中的坐标ui.openGLWidget->move(50, 50);testVtk3D();
}

构造一个testVtk3D函数,用于绘制点云,并使用vtkCameraOrientationWidget类创建一个坐标轴对象,由于testVtk3D在构造函数中调用,需要在头文件中将其定义为全局变量。另外,VTK使用的是智能指针vtkSmartPointer,无需管理其释放问题,VTK还提供vtkNew类的智能指针,
vtkSmartPointer与vtkNew两者主要的使用区别在于:前者多用于全局变量,后者多用于局部变量

	//在头文件中定义为全局变量vtkSmartPointer<vtkCameraOrientationWidget> cameraOrientationWidget;
void QVtkDemo2::testVtk3D()
{//创建着色器对象vtkSmartPointer<vtkRenderer> g_vtkRenderer = vtkSmartPointer<vtkRenderer>::New();//设置背景颜色g_vtkRenderer->SetBackground(.1, .2, .4);//创建point对象vtkSmartPointer<vtkPoints> g_vtkPoints = vtkSmartPointer<vtkPoints>::New();//创建cell对象vtkSmartPointer<vtkCellArray> g_vtkVertices = vtkSmartPointer<vtkCellArray>::New();vtkIdType id[1];//随机生成200个点for (int i = 0; i < 200; i++){float x = rand() % 10;float y = rand() % 10;float z = rand() % 10;id[0] = g_vtkPoints->InsertNextPoint(x, y, z);g_vtkVertices->InsertNextCell(1, id);}//创建poly对象vtkSmartPointer<vtkPolyData> g_vtkpolyData = vtkSmartPointer<vtkPolyData>::New();g_vtkpolyData->SetPoints(g_vtkPoints);g_vtkpolyData->SetVerts(g_vtkVertices);//创建polyMappervtkSmartPointer<vtkPolyDataMapper> g_vtkpointsMapper = vtkSmartPointer<vtkPolyDataMapper>::New();g_vtkpointsMapper->SetInputData(g_vtkpolyData);//创建ActorvtkSmartPointer<vtkActor> g_vtkpointsActor = vtkSmartPointer<vtkActor>::New();g_vtkpointsActor->SetMapper(g_vtkpointsMapper);g_vtkpointsActor->GetProperty()->SetPointSize(3);//设置点的大小g_vtkRenderer->AddActor(g_vtkpointsActor);//根据点云的包围盒,寻找最佳的显示视点位置g_vtkRenderer->ResetCamera();//ui中的绘制窗口添加定义的着色器ui.openGLWidget->renderWindow()->AddRenderer(g_vtkRenderer);//开始三维渲染ui.openGLWidget->renderWindow()->Render();//绘制坐标轴cameraOrientationWidget = vtkSmartPointer<vtkCameraOrientationWidget>::New();cameraOrientationWidget->SetInteractor(ui.openGLWidget->interactor());cameraOrientationWidget->SetParentRenderer(g_vtkRenderer);cameraOrientationWidget->SetEnabled(1);return;
}

运行效果如下图
在这里插入图片描述

VTK根据Z值绘制点云颜色

void QVtkDemo2::testVtk3D()
{//创建着色器对象vtkSmartPointer<vtkRenderer> g_vtkRenderer = vtkSmartPointer<vtkRenderer>::New();//设置背景颜色g_vtkRenderer->SetBackground(.1, .2, .4);//创建point对象vtkSmartPointer<vtkPoints> g_vtkPoints = vtkSmartPointer<vtkPoints>::New();g_vtkPoints->SetNumberOfPoints(200);//创建cell对象vtkSmartPointer<vtkCellArray> g_vtkVertices = vtkSmartPointer<vtkCellArray>::New();vtkIdType id[1];//随机生成200个点float minz = VTK_FLOAT_MAX, maxz = VTK_FLOAT_MIN;for (int i = 0; i < 200; i++){float x = rand() % 10;float y = rand() % 10;float z = rand() % 10;//提前申请了points的数量,使用set比insert速度更快g_vtkPoints->SetPoint(i, x, y, z);id[0] = i;g_vtkVertices->InsertNextCell(1, id);if (z > maxz){maxz = z;}if (z < minz){minz = z;}}//创建poly对象vtkSmartPointer<vtkPolyData> g_vtkpolyData = vtkSmartPointer<vtkPolyData>::New();g_vtkpolyData->SetPoints(g_vtkPoints);g_vtkpolyData->SetVerts(g_vtkVertices);vtkSmartPointer<vtkVertexGlyphFilter> g_glyphFilter = vtkSmartPointer<vtkVertexGlyphFilter>::New();g_glyphFilter->SetInputData(g_vtkpolyData);g_glyphFilter->Update();vtkSmartPointer<vtkElevationFilter> g_elevationFilter = vtkSmartPointer<vtkElevationFilter>::New();g_elevationFilter->SetInputConnection(g_glyphFilter->GetOutputPort());g_elevationFilter->SetLowPoint(0, 0, minz);g_elevationFilter->SetHighPoint(0, 0, maxz);//创建polyMappervtkSmartPointer<vtkPolyDataMapper> g_vtkpointsMapper = vtkSmartPointer<vtkPolyDataMapper>::New();g_vtkpointsMapper->SetInputConnection(g_elevationFilter->GetOutputPort());//创建ActorvtkSmartPointer<vtkActor> g_vtkpointsActor = vtkSmartPointer<vtkActor>::New();g_vtkpointsActor->SetMapper(g_vtkpointsMapper);g_vtkpointsActor->GetProperty()->SetPointSize(3);//设置点的大小g_vtkRenderer->AddActor(g_vtkpointsActor);//建立查找表,将Z深度映射为一个查找表,表的值对应不同的颜色vtkNew<vtkLookupTable> lut = vtkNew<vtkLookupTable>::vtkNew();lut->SetNumberOfTableValues(7);lut->SetHueRange(0.0, 0.67); //这里是红到蓝,设置<0.67,1>为蓝到红lut->SetTableRange(minz, maxz);lut->Build();//创建色谱栏vtkNew<vtkScalarBarActor> colorBar = vtkNew<vtkScalarBarActor>::vtkNew();colorBar->SetLookupTable(lut);colorBar->SetNumberOfLabels(7);colorBar->SetBarRatio(0.10);colorBar->SetUnconstrainedFontSize(0.05);colorBar->SetMaximumHeightInPixels(100);colorBar->SetDisplayPosition(500, 80);g_vtkRenderer->AddActor2D(colorBar);//根据点云的包围盒,寻找最佳的显示视点位置g_vtkRenderer->ResetCamera();//ui中的绘制窗口添加定义的着色器ui.openGLWidget->renderWindow()->AddRenderer(g_vtkRenderer);//开始三维渲染ui.openGLWidget->renderWindow()->Render();//绘制坐标轴cameraOrientationWidget = vtkSmartPointer<vtkCameraOrientationWidget>::New();cameraOrientationWidget->SetInteractor(ui.openGLWidget->interactor());cameraOrientationWidget->SetParentRenderer(g_vtkRenderer);cameraOrientationWidget->SetEnabled(1);return;
}

在这里插入图片描述

VTK赋予点云真实纹理信息(灰度\彩色)

这个功能的需要,是因为重建点云是一个“白模”或像上一节中的深度颜色映射图一样,有时候会需要点云贴上相机拍摄的灰度纹理或彩色纹理。下面的代码中,我定义了vtkUnsignedCharArray的指针,对256个点,分别赋予了一个颜色,R=G=B的情况就是灰度。由此,可实现点云真实纹理的显示。

void QVtkDemo2::testVtk3D()
{//创建着色器对象vtkSmartPointer<vtkRenderer> g_vtkRenderer = vtkSmartPointer<vtkRenderer>::New();//设置背景颜色g_vtkRenderer->SetBackground(.1, .2, .4);//创建point对象vtkSmartPointer<vtkPoints> g_vtkPoints = vtkSmartPointer<vtkPoints>::New();g_vtkPoints->SetNumberOfPoints(256);//创建cell对象vtkSmartPointer<vtkCellArray> g_vtkVertices = vtkSmartPointer<vtkCellArray>::New();vtkIdType id[1];vtkSmartPointer<vtkUnsignedCharArray> ptColor = vtkSmartPointer<vtkUnsignedCharArray>::New();ptColor->SetNumberOfTuples(256);ptColor->SetNumberOfComponents(3);//随机生成256个点, 每个点一个灰度值float minz = VTK_FLOAT_MAX, maxz = VTK_FLOAT_MIN;for (int i = 0; i < 256; i++){float x = rand() % 10;float y = rand() % 10;float z = rand() % 10;//提前申请了points的数量,使用set比insert速度更快g_vtkPoints->SetPoint(i, x, y, z);id[0] = i;g_vtkVertices->InsertNextCell(1, id);//赋予每一个点一个RGB值,R=G=B显示灰度,根据需要修改程序unsigned char rgb[3];rgb[0] = i;rgb[1] = i;rgb[2] = i;ptColor->InsertTypedTuple(i, rgb);}//创建poly对象vtkSmartPointer<vtkPolyData> g_vtkpolyData = vtkSmartPointer<vtkPolyData>::New();g_vtkpolyData->SetPoints(g_vtkPoints);g_vtkpolyData->SetVerts(g_vtkVertices);g_vtkpolyData->GetPointData()->SetScalars(ptColor);//创建polyMappervtkSmartPointer<vtkPolyDataMapper> g_vtkpointsMapper = vtkSmartPointer<vtkPolyDataMapper>::New();g_vtkpointsMapper->SetInputData(g_vtkpolyData);//创建ActorvtkSmartPointer<vtkActor> g_vtkpointsActor = vtkSmartPointer<vtkActor>::New();g_vtkpointsActor->SetMapper(g_vtkpointsMapper);g_vtkpointsActor->GetProperty()->SetPointSize(3);//设置点的大小g_vtkRenderer->AddActor(g_vtkpointsActor);//根据点云的包围盒,寻找最佳的显示视点位置g_vtkRenderer->ResetCamera();//ui中的绘制窗口添加定义的着色器ui.openGLWidget->renderWindow()->AddRenderer(g_vtkRenderer);//开始三维渲染ui.openGLWidget->renderWindow()->Render();//绘制坐标轴cameraOrientationWidget = vtkSmartPointer<vtkCameraOrientationWidget>::New();cameraOrientationWidget->SetInteractor(ui.openGLWidget->interactor());cameraOrientationWidget->SetParentRenderer(g_vtkRenderer);cameraOrientationWidget->SetEnabled(1);return;
}

在这里插入图片描述

petal_20240322_142336

相关文章:

  • STM32F103 CubeMX 使用USB生成键盘设备
  • 蓝桥杯刷题(十四)
  • 分布式系统面试全集通第一篇(dubbo+redis+zookeeper----分布式+CAP+BASE+分布式事务+分布式锁)
  • 千益畅行 || 共享旅游卡推广运营怎么做?
  • YOLOv8融入低照度图像增强算法---传统算法篇
  • EtherCAT转RS232网关在风电领域的应用
  • 虹科Pico汽车示波器 | 免拆诊断案例 | 2018款东风风神AX7车发动机怠速抖动、加速无力
  • Q_STATIC_ASSERT_X作用
  • 一些常见的与 Vim 相关的文件类型及其描述
  • 服务器呀服务器,一个虚拟专用服务器的使用教程
  • hadoop基本概念
  • 影视类视频片段分割
  • node项目中express的使用
  • pytest和unittest 如何选择?
  • 中文分词库盘点 Python windows
  • Google 是如何开发 Web 框架的
  • JS中 map, filter, some, every, forEach, for in, for of 用法总结
  • C++11: atomic 头文件
  • Docker容器管理
  • Git学习与使用心得(1)—— 初始化
  • Java|序列化异常StreamCorruptedException的解决方法
  • mockjs让前端开发独立于后端
  • MYSQL如何对数据进行自动化升级--以如果某数据表存在并且某字段不存在时则执行更新操作为例...
  • Next.js之基础概念(二)
  • node入门
  • Swift 中的尾递归和蹦床
  • Vue源码解析(二)Vue的双向绑定讲解及实现
  • 对话 CTO〡听神策数据 CTO 曹犟描绘数据分析行业的无限可能
  • 聊聊hikari连接池的leakDetectionThreshold
  • 吴恩达Deep Learning课程练习题参考答案——R语言版
  • 主流的CSS水平和垂直居中技术大全
  • 1.Ext JS 建立web开发工程
  • ionic异常记录
  • 好程序员web前端教程分享CSS不同元素margin的计算 ...
  • 进程与线程(三)——进程/线程间通信
  • 智能情侣枕Pillow Talk,倾听彼此的心跳
  • ​HTTP与HTTPS:网络通信的安全卫士
  • #stm32驱动外设模块总结w5500模块
  • (3)(3.5) 遥测无线电区域条例
  • (3)选择元素——(14)接触DOM元素(Accessing DOM elements)
  • (done) ROC曲线 和 AUC值 分别是什么?
  • (亲测成功)在centos7.5上安装kvm,通过VNC远程连接并创建多台ubuntu虚拟机(ubuntu server版本)...
  • (原創) 如何解决make kernel时『clock skew detected』的warning? (OS) (Linux)
  • (转载)虚幻引擎3--【UnrealScript教程】章节一:20.location和rotation
  • .bat批处理(五):遍历指定目录下资源文件并更新
  • .Net Core 中间件验签
  • @JsonSerialize注解的使用
  • @NoArgsConstructor和@AllArgsConstructor,@Builder
  • @zabbix数据库历史与趋势数据占用优化(mysql存储查询)
  • [ C++ ] STL_vector -- 迭代器失效问题
  • [ 代码审计篇 ] 代码审计案例详解(一) SQL注入代码审计案例
  • [ 转载 ] SharePoint 资料
  • [20190401]关于semtimedop函数调用.txt
  • [AIGC] Spring Interceptor 拦截器详解
  • [Android开源]EasySharedPreferences:优雅的进行SharedPreferences数据存储操作