VTK——模拟深度相机拍摄深度图(RGB-D)

1.设置vtkCamera内参

已知相机内参为:fx、fy、cx、cy,图像尺寸为:width、height
相机相对于世界坐标系的外参矩阵为extrinsicMatrix4x4,即相对于世界坐标系的旋转平移。如果不存在外参,则该矩阵为单位矩阵。
首先保证renderWindow的尺寸也设置为width、height

  // 将相机相对世界坐标系的外参赋值给相机
  camera->SetModelTransformMatrix(extrinsicMatrix4x4);

  // 由于SetModelTransformMatrix已经将规定了相机与世界坐标系的关系,此时相机设置Position的参照系为相机自己的参照系,此时相机应当处于原点
  camera->SetPosition(0, 0, 0);
  // 按照深度相机定义,相机应当看向Z+方向
  camera->SetFocalPoint(0, 0, 1);
  // 相机坐标系x沿u方向,y沿v方向,因此y是向下的
  camera->SetViewUp(0,-1,0);

  // 设置深度范围,按照相机默认参数即可,米单位
  camera->SetClippingRange(depth_min, depth_max);

  // 将主点转化为归一化的图像坐标系
  double wcx = -2*(cx - double(width)/2) / width;
  double wcy =  2*(cy - double(height)/2) / height;
  camera->SetWindowCenter(wcx, wcy);

  // 将焦距转化为视场角
  double view_angle = (2.0 * std::atan2( height/2.0, fy)) * 180.d / PI;
  camera->SetViewAngle( view_angle );

2.拍摄彩色图和深度图

2.1.拍摄彩色图

使用vtkWindowToImageFiltervtkJPEGWriter即可将renderWindow中的内容保存为图片。主要代码如下:

	m_renderWindow->Render();
	vtkSmartPointer<vtkWindowToImageFilter> wti = vtkSmartPointer<vtkWindowToImageFilter>::New();
	wti->SetInput(m_renderWindow);
	vtkSmartPointer<vtkJPEGWriter> jpegWriter = vtkSmartPointer<vtkJPEGWriter>::New();
	jpegWriter->SetFileName(filename);
	jpegWriter->SetInputConnection(wti->GetOutputPort());
	jpegWriter->Write();
	m_renderWindow->Finalize();

测试拍摄的图片如下:

在这里插入图片描述

2.2.拍摄深度图

第一节中已经将相机的内参赋值给vtkCamera,则使用ZBufferDisplayToWorld转化,完成深度图的采集。主要代码如下:

	// 使用OpenCV的CV_16UC1保存深度图
	cv::Mat depthImage(cv::Size(width, height), CV_16UC1);
	// 获取到renderWindow的ZBuffer(ZBuffer是0~1的深度值,范围在vtkCamera.SetClippingRange中规定)
	float * data = m_renderWindow->GetZbufferData(0, 0, width- 1, height - 1);
	double wPos[4];
	// 用于将世界坐标系转化为相机坐标系下深度值,外参矩阵的第三行。
	double m20 = extrinsicMatrix4x4(2, 0);
	double m21 = extrinsicMatrix4x4(2, 1);
	double m22 = extrinsicMatrix4x4(2, 2);
	double m23 = extrinsicMatrix4x4(2, 3);

	for (int y = 0; y < height; y++)
	{
		uint16_t * dData = depthImage.ptr<uint16_t>(y);
		for (int x = 0; x < width; x++)
		{
			// 获取ZBuffer对应数值
			float depth = data[y*width+ x];
			// 为1时表示无穷远,无深度
			if (depth == 1)
			{
				dData[x] = 0;
			}
			else 
			{
				// 将zBuffer转化为世界坐标系点坐标
				vtkInteractorObserver::ComputeDisplayToWorld(m_render, x, y, depth, wPos);
				// 将世界坐标系点坐标,转化为相机坐标系下Z,即深度
				float z = wPos[0] * m20 + wPos[1] * m21 + wPos[2] * m22 + m23;
				// 将米单位转化为毫米单位uint16_t进行存储
				dData[x] = (uint16_t)(z * 1000);
			}
		}
	}
	delete data;
	// 由于vtkRenderWindow的x、y方向与相机的不一致,需要进行flip。
	cv::flip(depthImage, depthImage, 0);
	// 保存深度图
	cv::imwrite(filename, depthImage);

保存的深度图如下所示(与上述彩色图对应):

在这里插入图片描述

3.验证

使用相机内参,将采集到的深度图换算为相机坐标系下三维点云,如下所示:

在这里插入图片描述
使用外参进行旋转平移,得到如下结果:

在这里插入图片描述
可以看到换算到世界坐标系下的三维点云与之前拍摄的模型完全重合。
以上完成了使用VTK模拟深度相机拍摄RGB-D图像的全过程。

  • 6
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
### 回答1: vtk是一种图形库,用于可视化数据。在vtk中,“点”、“线”和“面”是常见的几何元素。下面是关于这些元素的一些示例: 1. 点(Point):点是空间中具有坐标位置的最基本的几何元素。在vtk中,我们可以创建一个或多个点,并指定它们的坐标。例如,我们可以创建一个点的集合,表示星空中的一些恒星的位置。每个点都有自己的坐标,可以在三维空间中进行可视化。 2. 线(Line):线是由两个或更多个连接起来的点组成的几何形状。在vtk中,我们可以使用点的坐标来创建一条直线。例如,我们可以创建一个由两个点组成的线,表示一条直线段的路径。这条直线可以用来表示一条河流的流程,或者是一辆车在道路上行驶的路径。 3. 面(Surface):面是由三个或更多个连接起来的点和线组成的几何形状。在vtk中,我们可以使用点的坐标和线的连接关系来创建一个面。例如,我们可以创建一个三角形的面,通过指定三个点的坐标来定义。这个三角形可以用来表示一个地面的形状,或者是一个房屋的屋顶的形状。 总之,vtk提供了一种便捷的方式来创建和可视化各种几何元素,包括点、线和面。通过使用vtk,我们可以将这些几何元素在三维空间中进行可视化,并用于表示和展示各种数据的形状和结构。 ### 回答2: VTK(Visualization Toolkit)是一个强大的图形可视化库,它提供了丰富的功能和工具,可以用于创建各种类型的图形对象和可视化效果。在VTK中,可以使用点、线和面作为基本的图形元素。 在VTK中,点是最简单的图形元素之一。它可以用于表示空间中的一个坐标点,具有位置属性。例如,我们可以使用VTK创建一个点的可视化效果,通过设置其位置和颜色来定义点的属性,从而实现对点的可视化表达。 线是由多个点连接而成的线段。在VTK中,可以使用一系列的点来创建一条线,并通过设置线的属性,如线宽、颜色、透明度等来实现线的可视化效果。例如,我们可以通过VTK创建一个由多个点组成的路径,用来表示动态的物体运动轨迹。 面是由多条连续的线组成的封闭区域。在VTK中,可以使用一系列的坐标点来定义一个封闭的多边形,并通过设置面的属性,如颜色、透明度、纹理等来实现面的可视化效果。例如,我们可以使用VTK创建一个立方体的可视化效果,通过定义六个面和对应的坐标点来表示立方体的各个面。 总结起来,VTK中的点、线和面都是用于表示图形对象的基本元素,可以通过设置它们的属性来实现各种形式的可视化效果。无论是单独使用还是组合使用,这些元素都为图形的创建和可视化提供了灵活和多样的选择。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值