目录
PCL点云转深度图、求深度图边界并显示代码
详细说明看注释
#include <iostream>
#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/features/range_image_border_extractor.h>
#include <pcl/console/parse.h>
#include <pcl/common/file_io.h> // for getFilenameWithoutExtension
typedef pcl::PointXYZ PointType;
// --------------------
// -----Parameters-----
// --------------------
float angular_resolution = 0.5f;
pcl::RangeImage::CoordinateFrame coordinate_frame = pcl::RangeImage::CAMERA_FRAME;
bool setUnseenToMaxRange = false;
int
main(int argc, char** argv)
{
angular_resolution = pcl::deg2rad(angular_resolution);
// ------------------------------------------------------------------
// -----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;
pcl::PointCloud<pcl::PointWithViewpoint> far_ranges;
Eigen::Affine3f scene_sensor_pose(Eigen::Affine3f::Identity());
// Fill in the cloud data
pcl::PCDReader reader;
reader.read("rabbit.pcd", point_cloud);
// -----------------------------------------------
// -----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, pcl::deg2rad(360.0f), pcl::deg2rad(180.0f),
scene_sensor_pose, coordinate_frame, noise_level, min_range, border_size);
range_image.integrateFarRanges(far_ranges);
if (setUnseenToMaxRange)
range_image.setUnseenToMaxRange();
// --------------------------------------------
// -----Open 3D viewer and add point cloud-----
// --------------------------------------------
pcl::visualization::PCLVisualizer viewer("3D Viewer");
viewer.setBackgroundColor(1, 1, 1);
viewer.addCoordinateSystem(1.0f, "global");
pcl::visualization::PointCloudColorHandlerCustom<PointType> point_cloud_color_handler(point_cloud_ptr, 0, 0, 0);
viewer.addPointCloud(point_cloud_ptr, point_cloud_color_handler, "original point cloud");
// -------------------------
// -----Extract borders-----
// -------------------------
pcl::RangeImageBorderExtractor border_extractor(&range_image);
pcl::PointCloud<pcl::BorderDescription> border_descriptions;
border_extractor.compute(border_descriptions);
// ----------------------------------
// -----Show points in 3D viewer-----
// ----------------------------------
pcl::PointCloud<pcl::PointWithRange>::Ptr border_points_ptr(new pcl::PointCloud<pcl::PointWithRange>),
veil_points_ptr(new pcl::PointCloud<pcl::PointWithRange>),
shadow_points_ptr(new pcl::PointCloud<pcl::PointWithRange>);
pcl::PointCloud<pcl::PointWithRange>& border_points = *border_points_ptr,
& veil_points = *veil_points_ptr,
& shadow_points = *shadow_points_ptr;
for (int y = 0; y < (int)range_image.height; ++y)
{
for (int x = 0; x < (int)range_image.width; ++x)
{
if (border_descriptions[y * range_image.width + x].traits[pcl::BORDER_TRAIT__OBSTACLE_BORDER])
border_points.points.push_back(range_image[y * range_image.width + x]);
if (border_descriptions[y * range_image.width + x].traits[pcl::BORDER_TRAIT__VEIL_POINT])
veil_points.points.push_back(range_image[y * range_image.width + x]);
if (border_descriptions[y * range_image.width + x].traits[pcl::BORDER_TRAIT__SHADOW_BORDER])
shadow_points.points.push_back(range_image[y * range_image.width + x]);
}
}
pcl::visualization::PointCloudColorHandlerCustom<pcl::PointWithRange> border_points_color_handler(border_points_ptr, 0, 255, 0);//绿色,物体的边界
viewer.addPointCloud<pcl::PointWithRange>(border_points_ptr, border_points_color_handler, "border points");
viewer.setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 7, "border points");
pcl::visualization::PointCloudColorHandlerCustom<pcl::PointWithRange> veil_points_color_handler(veil_points_ptr, 255, 0, 0);//红色,物体与背景之间的过度点,雷达比较多
viewer.addPointCloud<pcl::PointWithRange>(veil_points_ptr, veil_points_color_handler, "veil points");
viewer.setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 7, "veil points");
pcl::visualization::PointCloudColorHandlerCustom<pcl::PointWithRange> shadow_points_color_handler(shadow_points_ptr, 0, 0, 255);//蓝色,是阴影的边界
viewer.addPointCloud<pcl::PointWithRange>(shadow_points_ptr, shadow_points_color_handler, "shadow points");
viewer.setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 7, "shadow points");
//-------------------------------------
// -----Show points on range image-----
// ------------------------------------
pcl::visualization::RangeImageVisualizer* range_image_borders_widget = NULL;
range_image_borders_widget =
pcl::visualization::RangeImageVisualizer::getRangeImageBordersWidget(range_image, -std::numeric_limits<float>::infinity(), std::numeric_limits<float>::infinity(), false,
border_descriptions, "Range image with borders");
// -------------------------------------
//--------------------
// -----Main loop-----
//--------------------
while (!viewer.wasStopped())
{
range_image_borders_widget->spinOnce();
viewer.spinOnce();
}
}
运行结果
深度图和边缘
点云显示的边缘
理论说明和结果分析
PCL中点云转换
核心代码
float angular_resolution = 0.5f;
pcl::RangeImage::CoordinateFrame coordinate_frame = pcl::RangeImage::CAMERA_FRAME;
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, pcl::deg2rad(360.0f), pcl::deg2rad(180.0f),
scene_sensor_pose, coordinate_frame, noise_level, min_range, border_size);
range_image.integrateFarRanges(far_ranges);
if (setUnseenToMaxRange)
range_image.setUnseenToMaxRange();
核心函数
createFromPointCloud,按照函数参数的顺序依次设置:
point_cloud:输入点云
angular_resolution:角度分辨率,例如 角度分辨率应为0.5度,这意味着相邻像素表示的光束相差0.5度;
pcl::deg2rad(360.0f):maxAngleWidth 视角宽360度,其实180度即可满足一般要求还能降低计算复杂度;
pcl::deg2rad(180.0f):, maxAngleHeight 视角高360度,其实180度即可满足一般要求还能降低计算复杂度;
scene_sensor_pose:sensorPose将虚拟传感器的6自由度位置定义为原点,横摇=俯仰=偏航=0
coordinate_frame:CAMERA_FRAME x向右,y向下,z轴向前。LASER_FRAME,x朝前,y朝左,z朝上。
noise_level:对于noiseLevel=0,是用所有单个Z创建。0.05意味着,与最近点之间最大距离为5cm的所有点用于计算范围。(这个描述可能不是很准确,希望大家能集思广益)
min_range:大于零的话,会忽略一些距离比较近的点;
border_size:图像边缘的宽度,点云往外扩充的一段边缘;
PCL中边缘检测
核心代码
pcl::RangeImageBorderExtractor border_extractor(&range_image);
pcl::PointCloud<pcl::BorderDescription> border_descriptions;
border_extractor.compute(border_descriptions);
核心函数
RangeImageBorderExtractor.comput(border_descriptions)
输出存在border_descriptions中,包括3类边缘,分别是:
1、物体的边缘;
2、阴影区域的边缘;
3、物体边缘和阴影边缘之间的点集;
可以显示在点云图像中,和深度图像中,可以看程序运行结果;
参考: