PCL 透视投影变换(OpenGL)

本文介绍了透视投影的概念及其在现实生活中的表现,详细讲述了透视投影如何通过PCL库在OpenGL中模拟,包括相应的代码实现和效果展示。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、简介

在现实生活中,我们总会注意到离我们越远的东西看起来更小。这个神奇的效果被称之为透视(Perspective)。透视的效果在我们看一条无限长的高速公路或铁路时尤其明显,正如下面图片显示的这样:

由于透视的原因,平行线似乎在很远的地方看起来会相交。这正是透视投影(Perspective Projection)想要模仿的效果,它是使用透视投影矩阵来完成的。这个投影矩阵不仅将给定的平截头体范围映射到裁剪空间,同样还修改了每个顶点坐标(齐次坐标,x,y,z,w,其中w为尺度系数)的w值,从而使得离观察者越远的顶点坐标w分量越大。如下图所示:

被转换到裁剪空间的坐标都会在-w到w的范围之间(任何大于这个范围的对象都会被裁剪掉)。OpenGL要求所有可见的坐标都落在-1.0到1.0范围内从而作为最后的顶点着色器输出,因此一旦坐标在裁剪空间内,透视划分就会被应用到裁剪空间坐标:

### 透视投影与正交投影的基本原理 在三维图形渲染中,投影是一种将三维几何信息映射到二维平面的技术,主要分为透视投影和正交投影两种形式。透视投影模拟人眼视觉效果,近大远小,具有更强的真实感;而正交投影不考虑距离变化,保持物体大小不变,适用于工程制图和CAD等场景[^2]。 在透视投影中,三维空间中的点通过透视除法映射到标准化设备坐标(NDC)空间,其变换矩阵通常包含焦距、视场角等参数。正交投影则直接将三维空间映射到一个矩形视景体,不涉及透视除法,保持各维度比例一致。 ### PCL 中的透视投影与正交投影实现 PCL(Point Cloud Library)本身并不直接提供完整的投影变换接口,但可以通过 `pcl::RangeImage` 类生成深度图,并结合 `pcl::visualization` 模块进行可视化。`pcl::RangeImage` 支持从点云数据生成深度图,其核心原理是通过透视投影或正交投影将三维点映射到二维图像空间[^4]。 以下是一个基于 `pcl::RangeImage` 生成深度图并保存为 PNG 的示例: ```cpp #include <pcl/range_image/range_image.h> #include <pcl/io/pcd_io.h> #include <pcl/visualization/range_image_visualizer.h> #include <pcl/visualization/pcl_visualizer.h> #include <pcl/io/png_io.h> int main(int argc, char** argv) { pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>); pcl::io::loadPCDFile<pcl::PointXYZ>("input.pcd", *cloud); // 设置视角参数 Eigen::Affine3f scene_sensor_pose(Eigen::Translation3f(0.0f, 0.0f, 0.0f)); float angular_resolution = pcl::deg2rad(0.5f); // 角度分辨率 float max_angle_width = pcl::deg2rad(360.0f); // 最大水平角度 float max_angle_height = pcl::deg2rad(180.0f); // 最大垂直角度 Eigen::Affine3f sensor_pose = Eigen::Affine3f::Identity(); // 构建 RangeImage pcl::RangeImage range_image; range_image.createFromPointCloud(*cloud, angular_resolution, max_angle_width, max_angle_height, sensor_pose, pcl::RangeImage::PERSPECTIVE_PROJECTION, 0.0f); // 获取深度数据并生成RGB图像 float* ranges = range_image.getRangesArray(); unsigned char* rgb_image = pcl::visualization::FloatImageUtils::getVisualImage(ranges, range_image.width, range_image.height); // 保存为PNG图像 pcl::io::saveRgbPNGFile("depth_map.png", rgb_image, range_image.width, range_image.height); return 0; } ``` 在上述代码中,`pcl::RangeImage::PERSPECTIVE_PROJECTION` 表示使用透视投影方式生成深度图。若需使用正交投影,可以修改投影类型为 `pcl::RangeImage::ORTHOGRAPHIC_PROJECTION`,并设置适当的视景体参数。 ### 投影变换在点云可视化中的应用 在 PCL 的可视化模块中,`pcl::visualization::PCLVisualizer` 提供了设置相机参数的功能,允许用户调整视场角(FOV)、相机位置等参数,从而实现不同的投影效果。例如,通过设置较小的视场角可以获得更强的透视感,而较大的视场角则更接近正交投影的效果。 以下是一个设置相机参数以控制投影方式的示例: ```cpp #include <pcl/visualization/pcl_visualizer.h> pcl::visualization::PCLVisualizer::Ptr viewer(new pcl::visualization::PCLVisualizer("3D Viewer")); viewer->setBackgroundColor(0, 0, 0); viewer->addCoordinateSystem(1.0); // 添加点云 pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>); pcl::io::loadPCDFile<pcl::PointXYZ>("input.pcd", *cloud); viewer->addPointCloud<pcl::PointXYZ>(cloud, "sample cloud"); // 设置相机参数以模拟正交投影 viewer->getCamera()->setFocalPoint(0.0, 0.0, 0.0); viewer->getCamera()->setPosition(0.0, 0.0, 3.0); viewer->getCamera()->setViewUp(0.0, 1.0, 0.0); viewer->getCamera()->setClippingRange(0.01, 100.0); viewer->getCamera()->setWindowCenter(0.0, 0.0); viewer->getCamera()->setZoom(1.0); // 调整Zoom值可控制投影类型 viewer->spin(); ``` 在上述代码中,通过调整 `setZoom()` 的值可以控制投影的缩放比例,从而影响最终的视觉效果。较小的 `Zoom` 值接近正交投影,而较大的值则增强透视效果。 ### 总结 透视投影和正交投影在 PCL 中的实现主要依赖于 `pcl::RangeImage` 类和可视化模块的相机控制功能。透视投影适用于需要真实感的场景,如虚拟现实和三维重建;正交投影则适用于需要保持几何精度的工程应用。通过调整投影类型和相机参数,可以灵活地满足不同点云可视化需求[^4]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

大鱼BIGFISH

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

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

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

打赏作者

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

抵扣说明:

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

余额充值