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);
	//创建polyMapper
	vtkSmartPointer<vtkPolyDataMapper> g_vtkpointsMapper = vtkSmartPointer<vtkPolyDataMapper>::New();
	g_vtkpointsMapper->SetInputData(g_vtkpolyData);
	//创建Actor
	vtkSmartPointer<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);

	//创建polyMapper
	vtkSmartPointer<vtkPolyDataMapper> g_vtkpointsMapper = vtkSmartPointer<vtkPolyDataMapper>::New();
	g_vtkpointsMapper->SetInputConnection(g_elevationFilter->GetOutputPort());

	//创建Actor
	vtkSmartPointer<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);

	//创建polyMapper
	vtkSmartPointer<vtkPolyDataMapper> g_vtkpointsMapper = vtkSmartPointer<vtkPolyDataMapper>::New();
	g_vtkpointsMapper->SetInputData(g_vtkpolyData);

	//创建Actor
	vtkSmartPointer<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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

leaf_csdn

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

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

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

打赏作者

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

抵扣说明:

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

余额充值