写在前面:小白学习激光雷达、PCL点云库,不懂Linux不懂c++,非常艰难的学着,做出学习笔记,希望能对小白起步有所帮助,也希望能够得到大佬的指点。
本次程序实现的是可视化深度图像。采用了两种办法:
1、在3D视窗中,以点云的形式进行可视化(深度图像来源于点云)。
2、将深度值映射为颜色,以彩色图像的方式可视化深度图像。
既然PCL学的是点云库,那么我们最重要的是学习库函数,先搞明白干什么的,最后会用就可以了。
一次看懂例程真的太难了,分几次看吧还是/哭死
1、pcl::RangeImage::CoordinateFrame coordinate_frame = pcl::RangeImage::CAMERA_FRAME;
在PCL(Point Cloud Library)中,pcl::RangeImage::CoordinateFrame
是一个枚举类型,用于指定深度图像(RangeImage)的坐标框架。坐标框架定义了深度图像中像素的坐标系统,它可以是相机坐标系(CAMERA_FRAME)或激光坐标系(LASER_FRAME)。
pcl::RangeImage::CAMERA_FRAME
:表示深度图像中的像素坐标是相对于相机的坐标系统。在这种情况下,像素的x轴指向相机的右侧,y轴指向下方,z轴指向相机的前方。pcl::RangeImage::LASER_FRAME
:表示深度图像中的像素坐标是相对于激光扫描仪的坐标系统。在这种情况下,像素的x轴通常指向扫描仪的左侧,y轴指向扫描仪的上方,z轴指向扫描仪的前方。
例程:
#include <iostream>
// 引入PCL相关的头文件
#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/console/parse.h>
// 定义点类型为pcl::PointXYZ
typedef pcl::PointXYZ PointType;
// --------------------
// -----Parameters-----
// --------------------
// 初始化水平和垂直角分辨率(以度为单位)
float angular_resolution_x = 0.5f,
angular_resolution_y = angular_resolution_x;
// 设置坐标框架为相机坐标系
pcl::RangeImage::CoordinateFrame coordinate_frame = pcl::RangeImage::CAMERA_FRAME;
// 初始化实时更新标志为false
bool live_update = false;
// --------------
// -----Help-----
// --------------
// 打印使用帮助信息的函数
void
printUsage (const char* progName)
{
std::cout << "\n\nUsage: "<<progName<<" [options] <scene.pcd>\n\n"
<< "Options:\n"
<< "-------------------------------------------\n"
<< "-rx <float> angular resolution in degrees (default "<<angular_resolution_x<<")\n"
<< "-ry <float> angular resolution in degrees (default "<<angular_resolution_y<<")\n"
<< "-c <int> coordinate frame (default "<< (int)coordinate_frame<<")\n"
<< "-l live update - update the range image according to the selected view in the 3D viewer.\n"
<< "-h this help\n"
<< "\n\n";
}
// 设置查看器姿态的函数
void
setViewerPose (pcl::visualization::PCLVisualizer& viewer, const Eigen::Affine3f& viewer_pose)
{
// 计算相机位置、观察点和向上向量
Eigen::Vector3f pos_vector = viewer_pose * Eigen::Vector3f(0, 0, 0);
Eigen::Vector3f look_at_vector = viewer_pose.rotation () * Eigen::Vector3f(0, 0, 1) + pos_vector;
Eigen::Vector3f up_vector = viewer_pose.rotation () * Eigen::Vector3f(0, -1, 0);
// 设置查看器的相机参数
viewer.setCameraPosition (pos_vector[0], pos_vector[1], pos_vector[2],
look_at_vector[0], look_at_vector[1], look_at_vector[2],
up_vector[0], up_vector[1], up_vector[2]);
}
// --------------
// -----Main-----
// --------------
int
main (int argc, char** argv)
{
// --------------------------------------
// -----Parse Command Line Arguments-----
// --------------------------------------
// 检查是否请求帮助信息
if (pcl::console::find_argument (argc, argv, "-h") >= 0)
{
printUsage (argv[0]);
return 0;
}
// 检查是否启用实时更新
if (pcl::console::find_argument (argc, argv, "-l") >= 0)
{
live_update = true;
std::cout << "Live update is on.\n";
}
// 解析水平和垂直角分辨率
if (pcl::console::parse (argc, argv, "-rx", angular_resolution_x) >= 0)
std::cout << "Setting angular resolution in x-direction to "<<angular_resolution_x<<"deg.\n";
if (pcl::console::parse (argc, argv, "-ry", angular_resolution_y) >= 0)
std::cout << "Setting angular resolution in y-direction to "<<angular_resolution_y<<"deg.\n";
int tmp_coordinate_frame;
// 解析坐标框架
if (pcl::console::parse (argc, argv, "-c", tmp_coordinate_frame) >= 0)
{
coordinate_frame = pcl::RangeImage::CoordinateFrame (tmp_coordinate_frame);
std::cout << "Using coordinate frame "<< (int)coordinate_frame<<".\n";
}
// 将角分辨率从度转换为弧度
angular_resolution_x = pcl::deg2rad (angular_resolution_x);
angular_resolution_y = pcl::deg2rad (angular_resolution_y);
// ------------------------------------------------------------------
// -----Read pcd file or create example point cloud if not given-----
// ------------------------------------------------------------------
// 创建点云指针
pcl::PointCloud<PointType>::Ptr point_cloud_ptr (new pcl::PointCloud<PointType>);
pcl::PointCloud<PointType>& point_cloud = *point_cloud_ptr;
// 初始化场景传感器姿态
Eigen::Affine3f scene_sensor_pose (Eigen::Affine3f::Identity ());
//
// 查找命令行参数中是否有PCD文件
std::vector<int> pcd_filename_indices = pcl::console::parse_file_extension_argument (argc, argv, "pcd");
if (!pcd_filename_indices.empty ())
{
// 获取PCD文件名
std::string filename = argv[pcd_filename_indices[0]];
// 尝试加载PCD文件
if (pcl::io::loadPCDFile (filename, point_cloud) == -1)
{
std::cout << "Was not able to open file \""<<filename<<"\".\n";
printUsage (argv[0]);
return 0;
}
// 设置场景传感器姿态
scene_sensor_pose = Eigen::Affine3f (Eigen::Translation3f (point_cloud.sensor_origin_[0],
point_cloud.sensor_origin_[1],
point_cloud.sensor_origin_[2])) *
Eigen::Affine3f (point_cloud.sensor_orientation_);
}
else
{
// 如果没有提供PCD文件,则创建一个示例点云
std::cout << "\nNo *.pcd file given => Generating example point cloud.\n\n";
for (float x=-0.5f; x<=0.5f; x+=0.01f)
{
for (float y=-0.5f; y<=0.5f; y+=0.01f)
{
PointType point; point.x = x; point.y = y; point.z = 2.0f - y;
point_cloud.push_back (point);
}
}
point_cloud.width = point_cloud.size (); point_cloud.height = 1;
}
// -----------------------------------------------
// -----Create RangeImage from the PointCloud-----
// -----------------------------------------------
// 初始化噪声水平和最小范围
float noise_level = 0.0;
float min_range = 0.0f;
int border_size = 1;
// 创建深度图像指针
pcl::RangeImage::Ptr range_image_ptr(new pcl::RangeImage);
pcl::RangeImage& range_image = *range_image_ptr;
// 从点云创建深度图像
range_image.createFromPointCloud (point_cloud, angular_resolution_x, angular_resolution_y,
pcl::deg2rad (360.0f), pcl::deg2rad (180.0f),
scene_sensor_pose, coordinate_frame, noise_level, min_range, border_size);
// --------------------------------------------
// -----Open 3D viewer and add point cloud-----
// --------------------------------------------
// 创建3D查看器
pcl::visualization::PCLVisualizer viewer ("3D Viewer");
viewer.setBackgroundColor (1, 1, 1);
// 创建深度图像的颜色处理程序并添加到查看器
pcl::visualization::PointCloudColorHandlerCustom<pcl::PointWithRange> range_image_color_handler (range_image_ptr, 0, 0, 0);
viewer.addPointCloud (range_image_ptr, range_image_color_handler, "range image");
viewer.setPointCloudRenderingProperties (pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 1, "range image");
//viewer.addCoordinateSystem (1.0f, "global");
//PointCloudColorHandlerCustom<PointType> point_cloud_color_handler (point_cloud_ptr, 150, 150, 150);
//viewer.addPointCloud (point_cloud_ptr, point_cloud_color_handler, "original point cloud");
viewer.initCameraParameters ();
// 设置查看器姿态
setViewerPose(viewer, range_image.getTransformationToWorldSystem ());
// --------------------------
// -----Show range image-----
// --------------------------
// 创建深度图像可视化窗口
pcl::visualization::RangeImageVisualizer range_image_widget ("Range image");
range_image_widget.showRangeImage (range_image);
//--------------------
// -----Main loop-----
//--------------------
// 主循环,用于更新查看器和深度图像
while (!viewer.wasStopped ())
{
range_image_widget.spinOnce ();
viewer.spinOnce ();
pcl_sleep (0.01);
// 如果启用实时更新,则根据查看器姿态更新深度图像
if (live_update)
{
scene_sensor_pose = viewer.getViewerPose();
range_image.createFromPointCloud (point_cloud, angular_resolution_x, angular_resolution_y,
pcl::deg2rad (360.0f), pcl::deg2rad (180.0f),
scene_sensor_pose, pcl::RangeImage::LASER_FRAME, noise_level, min_range, border_size);
range_image_widget.showRangeImage (range_image);
}
}
}