博主最近在做三维重建,之前就了解过pcl库,俗话说,二维处理靠opencv,三维处理靠pcl,那么这个点云库到底有什么神奇功能呢?博主才疏学浅,现在就学了如何将三维点显示和一些简单的滤波,在这里,对自己,也是对广大初学者都可以做个复习和简单的介绍。
首先如何将已有的三维点显示,博主这里是利用深度相机直接测得的深度,帧之间通过icp获得世界坐标系下的空间位姿,在这里,我们简单来看从深度照片中提取点云。
pcl::pointcloud<pcl::pointxyzrgb>::ptr pointcloud(new pcl::pointcloud<pcl::pointxyzrgb>);
//opencv提取点云
Mat color=imread("your adress");
Mat depth=imread("your adress",-1);
//遍历像素,还原深度和三维点
for(int v=0;v<color.rows;v++)
for(int u=0;u<color.cols;u++)
{
ushort d=depth.ptr<unsigned short>(v)[u];
//还原三维点
Point3d world;
world.z=double(d)/1000.0;
world.x=(u-cx)/fx*world.z;
world.y=(v-cy)/fy*world.z;
//定义点云类型(博主手码,类函数里面一些大小写就不区分了,大家自己写应该一眼就看得出)
pcl::xyzrgb pc;
pc.x=world.x;
pc.y=world.y;
pc.z=world.z;
pc.b=color.data[v*color.step+u*color.channels()];
pc.g=color.data[v*color.step+u*color.channels()+1];
pc.r=color.data[v*color.step+u*color.channels()+2];
pointcloud->push_back(pc);
}
//好了,至此你已经将照片上的像素点都添加到点云了,注意了,博主自己码的,所以类的名称大小写应该都是错的(QAQ),见谅。
pointcloud->is_dense=false;
//将照片保存
pcl::io::savepcdfilebinary("map.pcd",*pointcloud);
博主其实不懒,上面的代码大家将就看吧,对不起大家啊,不能复制黏贴哈哈。
好了,下面介绍两种常见的滤波,统计滤波和体素滤波,博主学的不深,简单来说,统计滤波是将空间上的点聚类,感觉是不是类似kmeans啊哈哈,然后去除孤立的点,一般用来去除带噪声的数据,而体素滤波是将一个很小空间上的点里面很多个点算它们的质心,博主感觉是用来消除重投影误差的把,意思是可能一个点被不同观测重新还原到了有些误差的不同位置,这样可以是整个空间更加趋于平滑,也为以后的稠密重建做好了准备。
废话不多说,博主懒了,直接上代码了,大家讲究看吧,实在不好意思了。
//统计滤波,存放点云
pointcloud::Ptr currentstatistical(new pointcloud);
//定义统计滤波类
pcl::StatisticalOutlierRemoval<pcl::PointXYZRGB> statistical_filter;
statistical_filter.setMeanK(50);
statistical_filter.setStddevMulThresh(1.0);
statistical_filter.setInputCloud(currentpoint);
statistical_filter.filter(*currentstatistical);
(*pointcloud_ptr)=(*pointcloud_ptr)+(*currentstatistical);
这是统计滤波,大家应该看得懂吧
pcl::VoxelGrid<pcl::PointXYZRGB> voxel_filter;
//设置最小单位
voxel_filter.setLeafSize(0.01,0.01,0.01);
voxel_filter.setInputCloud(pointcloud_ptr);
//定义点云类型存放滤波后的
pcl::PointCloud<pcl::PointXYZRGB>::Ptr current_voxelpoint;
voxel_filter.filter(*current_voxelpoint);
current_voxelpoint->swap(*pointcloud_ptr);
这是体素滤波,估计问题不大对应各位来说
各位再见