1.从一个深度图像中提取NARF特征点位置的NARF特征描述子。本节从给定的pcd文件中提取特征点,然后在这些位置估算特征描述子,接着在一个深度图像和三维视图中可视化这些特征点位置。
2.代码
#include <iostream>
#include <pcl/point_cloud.h>
#include <pcl/point_types.h>
#include <boost/thread/thread.hpp>
#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/keypoints/narf_keypoint.h>
#include <pcl/features/narf_descriptor.h>
using namespace std;
//参数 全局变量
typedef pcl::PointXYZ PointType;
float angular_resolution = 0.5f; //角坐标分辨率
float support_size = 0.2f; //感兴趣点的尺寸(球面的直径)
pcl::RangeImage::CoordinateFrame coordinate_frame = pcl::RangeImage::CAMERA_FRAME; //坐标框架:相机框架
bool rotation_invariant = true;
int main( )
{
angular_resolution = pcl::deg2rad(angular_resolution);//角度值转为弧度值
//读取pcd文件;如果没有指定文件,就创建样本点
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()); //仿射变换
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_); //设置传感器的姿势
pcl::io::loadPCDFile("D:\\pcd\\table_scene_mug_stereo_textured.pcd", point_cloud); //从磁盘读取pcd文件
/* //自己设置点云文件
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<pcl::RangeImage> range_image_ptr(new pcl::RangeImage); //创建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); //从点云创建深度图像
//打开3D观察图形窗口,并添加点云
pcl::visualization::PCLVisualizer viewer("3D 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.initCameraParameters();
//显示深度图像(平面图,上面的3D显示)
pcl::visualization::RangeImageVisualizer range_image_widget("Range image");
range_image_widget.showRangeImage(range_image);
//提取NARF关键点
pcl::RangeImageBorderExtractor range_image_border_extractor; //创建深度图像的边界提取器,用于提取NARF关键点
pcl::NarfKeypoint narf_keypoint_detector;//创建NARF对象
narf_keypoint_detector.setRangeImageBorderExtractor(&range_image_border_extractor);
narf_keypoint_detector.setRangeImage(&range_image);
narf_keypoint_detector.getParameters().support_size = support_size;
pcl::PointCloud<int> keypoint_indices; //用于存储关键点的索引
narf_keypoint_detector.compute(keypoint_indices); //计算NARF关键点
cout << "Found " << keypoint_indices.points.size() << " key points.\n";
//在3D图形窗口中显示关键点
pcl::PointCloud<pcl::PointXYZ>::Ptr keypoints_ptr(new pcl::PointCloud<pcl::PointXYZ>); //创建关键点指针
pcl::PointCloud<pcl::PointXYZ>& keypoints = *keypoints_ptr; //引用
keypoints.points.resize(keypoint_indices.points.size()); //点云变形,无序
for (size_t i = 0; i < keypoint_indices.points.size(); ++i) {
keypoints.points[i].getVector3fMap() = range_image.points[keypoint_indices.points[i]].getVector3fMap();
}
pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> keypoints_color_handler(keypoints_ptr, 0, 255, 0);
viewer.addPointCloud<pcl::PointXYZ>(keypoints_ptr, keypoints_color_handler, "keypoints");
viewer.setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 7, "keypoints");
//为特征点提取NARF描述子
vector<int> keypoint_indices2;
keypoint_indices2.resize(keypoint_indices.points.size());
for (unsigned int i = 0; i < keypoint_indices.size(); i++)
{
keypoint_indices2[i] = keypoint_indices.points[i];
}
//创建NarfDescriptor对象,输入数据(特征点索引和深度图像)
pcl::NarfDescriptor narf_descriptor(&range_image, &keypoint_indices2);
narf_descriptor.getParameters().support_size = support_size;//确定描述子区域大小
narf_descriptor.getParameters().rotation_invariant = rotation_invariant;
pcl::PointCloud<pcl::Narf36> narf_descriptors;
narf_descriptor.compute(narf_descriptors);
cout << "extracted" << narf_descriptors.size() << "descriptors for"
<< keypoint_indices.points.size()
<< "keypoints\n" << endl;
//Main loop
while (!viewer.wasStopped())
{
range_image_widget.spinOnce(); // 处理 GUI事件
viewer.spinOnce();
pcl_sleep(0.01);
}
}
3.显示