相比于其他的特征描述,ROPS需要三个输入数据:
- points: 输入点云
- indices: RoPS特征点的标号(即关键点在点云中的下标)
- triangles:三角面元
首先介绍一下我获取indices的方法。我是用ISS3D求得关键点之后,调用getKeypointsIndices()函数实现的。具体程序如下:
pcl::PointIndicesPtr indices(new pcl::PointIndices());
......ISS3D计算关键点算法部分省略......
*indices = *iss.getKeypointsIndices();
然后是获取triangles三角面元信息。这里我是通过.obj文件生成的triangle.txt文件。生成程序如下(此处建议另新建一工程进行生成):
#include <fstream>//fstream类是把程序和文件关联起来
ifstream ifs("此处填写要输入的本地文件地址,如F:\\a.obj", ifstream::in);
ofstream ofs("此处填写用于存放生成文件的地址及文件名和类型,如F:\\triangle.txt", ofstream::out);
if(!ifs.is_open()){
cout<<"error opening file. "
}
while(
char *c = new char[256];
if(!ifs.getline(c,256).eof()){break;}//到文件结尾循环结束
if(c[0] == 'f'){
int a[6]
sscanf(c,"f %d//%d %d//%d %d//%d", &a[0],&a[1], &a[2], &a[3], &a[4], &a[5]);
ofs<<a[0]-1<<" "<<a[2]-1<<" "<<a[4]-1<<endl;//-1的原因是obj格式的文件下标是从1开始存储的,而程序中是从0开始的
}
)
通过上面的程序就可以获取自己的trianle.txt文件了,接下来就是在加载面元信息了。程序如下:
ifstream ifs("生成triangle.txt文件的路径", ifstream::in);
vector<pcl::Vertices> triangles;
while(1){
pcl::Vertices triangle;
int a[3];
if(!ifs.getline(a, 3).eof()){break;}
triangle.push_back(a[0]);
triangle.push_back(a[1]);
triangle.push_back(a[2]);
triangles.push_back(triangle);
}
最后是实例化pcl::ROPSEstimation类
pcl::PointCloud<pcl::Histogram<135>>::Ptr rops_features(new pcl::PointCloud<pcl::Histogram<135>>())
float search_radius = 0.0285f;
int number_of_partition_bins = 5;
int number_of_rotations = 3;
pcl::ROPSEtimation<pcl::PointXYZ, pcl::Histogram<135>> rops;
pcl::search::KDTree<pcl::PointXYZ>::Ptr search_method(new pcl::search::KDTree<pcl::PointXYZ>);
search_method->setInputCloud(cloud);
rops.setSearchSurface(cloud);
rops.setInputCloud(cloud);
rops.setIndices(indices);
rops.setTriangles(triangles);
rops.setRadiusSearch(search_radius);
rops.setNumberOfPartitionBins(number_of_partition_bins);
rops.setNumberOfRotations(number_of_rotations);
rops.setSupportRadius(radius_search);
rops.compute(*rops_features);
经实践以上方法得到的indice和triangles 信息是正确的,但这里要注意生成triangle.txt文件时,要保证.obj文件和.pcd文件是对应的,否则就会出现段错误。
在这里补一个.obj转化为.pcd文件的程序。
#include <pcl/io/io.h>
#include <pcl/io/pcd_io.h>
#include <pcl/io/obj_io.h>
#include <pcl/PolygonMesh.h>
#include <pcl/point_cloud.h>
#include <pcl/io/vtk_lib_io.h>//loadPolygonFileOBJ所属头文件;
int main()
{
pcl::PolygonMesh mesh;
pcl::io::loadPolygonFileOBJ("F\\project\\a.obj", mesh);
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
pcl::fromPCLPointCloud2(mesh.cloud, *cloud);
pcl::io::savePCDFileASCII("F\\project\\a.pcd", *cloud);
return 0;
}