从深度图像中提取边界(从前景跨越到背景的位置定义为边界),其中,
物体边界:这是物体的最外层和阴影边界的可见点集;
阴影边界:毗邻与遮挡的背景上的点集;
Veil点集:在被遮挡物边界和阴影边界之间的内插点;
它们是有激光雷达获取的3D距离数据中的典型数据类型,这三类数据及深度图像的边界如图:
从磁盘中读取点云,创建深度图像并使其可视化,提取边界信息很重要的一点就是区分深度图像中当前视点不可见点集合和应该可见但处于传感器获取距离范围之外的点集 ,后者可以标记为典型边界,然而当前视点不可见点则不能成为边界,因此,如果后者的测量值存在,则提供那些超出传感器距离获取范围之外的数据对于边界的提取是非常重要的。
/* \author Bastian Steder */
#include
#include
#include
#include
#include
#include
#include
#include
typedef pcl::PointXYZ PointType;
// --------------------
// -----参数-----
// --------------------
float angular_resolution = 0.5f;
pcl::RangeImage::CoordinateFrame coordinate_frame = pcl::RangeImage::CAMERA_FRAME;
bool setUnseenToMaxRange = false;
// --------------
// -----帮助-----
// --------------
void
printUsage (const char* progName)
{
std::cout << "\n\nUsage: "<\n\n"
<< "Options:\n"
<< "-------------------------------------------\n"
<< "-r angular resolution in degrees (default "< coordinate frame (default "<< (int)coordinate_frame<<")\n"
<< "-m Treat all unseen points to max range\n"
<< "-h this help\n"
<< "\n\n";
}
// --------------
// -----主函数-----
// --------------
int
main (int argc, char** argv)
{
// --------------------------------------
// -----解析命令行参数-----
// --------------------------------------
if (pcl::console::find_argument (argc, argv, "-h") >= 0)
{
printUsage (argv[0]);
return 0;
}
if (pcl::console::find_argument (argc, argv, "-m") >= 0)
{
setUnseenToMaxRange = true;
cout << "Setting unseen values in range image to maximum range readings.\n";
}
int tmp_coordinate_frame;
if (pcl::console::parse (argc, argv, "-c", tmp_coordinate_frame) >= 0)
{
coordinate_frame = pcl::RangeImage::CoordinateFrame (tmp_coordinate_frame);
cout << "Using coordinate frame "<< (int)coordinate_frame<<".\n";
}
if (pcl::console::parse (argc, argv, "-r", angular_resolution) >= 0)
cout << "Setting angular resolution to "<::Ptr point_cloud_ptr (new pcl::PointCloud);
pcl::PointCloud& point_cloud = *point_cloud_ptr;
pcl::PointCloud far_ranges;
Eigen::Affine3f scene_sensor_pose (Eigen::Affine3f::Identity ());
std::vector pcd_filename_indices = pcl::console::parse_file_extension_argument (argc, argv, "pcd");
if (!pcd_filename_indices.empty ())
{
std::string filename = argv[pcd_filename_indices[0]];
if (pcl::io::loadPCDFile (filename, point_cloud) == -1)
{
cout << "Was not able to open file \""< Genarating 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.points.push_back (point);
}
}
point_cloud.width = (int) point_cloud.points.size (); point_cloud.height = 1;
}
// -----------------------------------------------
// -----从点云创建深度图像-----
// -----------------------------------------------
float noise_level = 0.0;
float min_range = 0.0f;
int border_size = 1;
boost::shared_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);
//命令行参数-m,使能setUnseenToMaxRange为true:设置所有不能观察到的点均为远距离点;
if (setUnseenToMaxRange)
range_image.setUnseenToMaxRange ();
// --------------------------------------------
// -----打开三维浏览器并添加点云-----
// --------------------------------------------
pcl::visualization::PCLVisualizer viewer ("3D Viewer");
viewer.setBackgroundColor (1, 1, 1);
viewer.addCoordinateSystem (1.0f);
pcl::visualization::PointCloudColorHandlerCustom point_cloud_color_handler (point_cloud_ptr, 0, 0, 0);
viewer.addPointCloud (point_cloud_ptr, point_cloud_color_handler, "original point cloud");
//PointCloudColorHandlerCustom range_image_color_handler (range_image_ptr, 150, 150, 150);
//viewer.addPointCloud (range_image_ptr, range_image_color_handler, "range image");
//viewer.setPointCloudRenderingProperties (PCL_VISUALIZER_POINT_SIZE, 2, "range image");
// -------------------------
// -----提取边界-----
// -------------------------
pcl::RangeImageBorderExtractor border_extractor (&range_image);
pcl::PointCloud border_descriptions;
border_extractor.compute (border_descriptions);
// ----------------------------------
// -----在三维浏览器中显示点集-----
// ----------------------------------
pcl::PointCloud::Ptr border_points_ptr(new pcl::PointCloud), veil_points_ptr(new pcl::PointCloud), shadow_points_ptr(new pcl::PointCloud);
pcl::PointCloud& 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.points[y*range_image.width + x].traits[pcl::BORDER_TRAIT__OBSTACLE_BORDER])
border_points.points.push_back (range_image.points[y*range_image.width + x]);
if (border_descriptions.points[y*range_image.width + x].traits[pcl::BORDER_TRAIT__VEIL_POINT])
veil_points.points.push_back (range_image.points[y*range_image.width + x]);
if (border_descriptions.points[y*range_image.width + x].traits[pcl::BORDER_TRAIT__SHADOW_BORDER])
shadow_points.points.push_back (range_image.points[y*range_image.width + x]);
}
}
pcl::visualization::PointCloudColorHandlerCustom border_points_color_handler (border_points_ptr, 0, 255, 0);
viewer.addPointCloud (border_points_ptr, border_points_color_handler, "border points");
viewer.setPointCloudRenderingProperties (pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 7, "border points");
pcl::visualization::PointCloudColorHandlerCustom veil_points_color_handler (veil_points_ptr, 255, 0, 0);
viewer.addPointCloud (veil_points_ptr, veil_points_color_handler, "veil points");
viewer.setPointCloudRenderingProperties (pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 7, "veil points");
pcl::visualization::PointCloudColorHandlerCustom shadow_points_color_handler (shadow_points_ptr, 0, 255, 255);
viewer.addPointCloud (shadow_points_ptr, shadow_points_color_handler, "shadow points");
viewer.setPointCloudRenderingProperties (pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 7, "shadow points");
//-------------------------------------
// -----在深度图像中显示点集-----
// ------------------------------------
pcl::visualization::RangeImageVisualizer* range_image_borders_widget = NULL;
range_image_borders_widget =
pcl::visualization::RangeImageVisualizer::getRangeImageBordersWidget (range_image, -std::numeric_limits::infinity (), std::numeric_limits::infinity (), false, border_descriptions, "Range image with borders" );
// -------------------------------------
//--------------------
// -----主循环-----
//--------------------
while (!viewer.wasStopped ())
{
range_image_borders_widget->spinOnce ();
viewer.spinOnce ();
pcl_sleep(0.01);
}
}
创建示例点云,运行命令:
结果图:
自定生成矩形状浮点型点云,检测出的边界用绿色较大的点表示,其他的点用默认的普通的大小点来表示。
读入pcd文件,运行命令:
使用其他的PCD文件来运行这个程序的时候会提示 Far ranges file far_ranges_filename does not exists, 这是因为在深度传感器得带深度图像并可视化图像的时候,我们都知道传感器的测量距离受硬件的限制,所以在这里就是要定义传感器看不到的距离,所以当我们自己使用kinect获取深度图像运行这个程序的时候直接使用命令 -m, 使用-m的原因是要设置传感器看不见的位置 Setting unseen values in range image to maximum range readings。
结果图:检测出的边界用绿色较大的点表示,其他的点用默认的普通的大小点来表示。