#include <iostream>
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
#include <pcl/visualization/cloud_viewer.h>
#include <pcl/visualization/histogram_visualizer.h>
#include <pcl/point_types.h>
#include <pcl/features/fpfh.h>
#include <pcl/filters/fast_bilateral.h>
#include <pcl/filters/passthrough.h>
#include <pcl/filters/radius_outlier_removal.h>
#include <pcl/filters/voxel_grid.h>
#include <pcl/features/normal_3d.h>
#include <pcl/visualization/pcl_plotter.h>
#include <vtkAutoInit.h>
#include <string.h>
#define vtkRenderingCore_AUTOINIT 3(vtkInteractionStyle,vtkRenderingFreeType,vtkRenderingOpenGL2)
VTK_MODULE_INIT(vtkRenderingOpenGL);
using namespace std;
pcl::PointCloud<pcl::PointXYZRGB>::Ptr computeFPFH(pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_origin, pcl::PointCloud<pcl::Normal>::Ptr cloud_normals)
{
float radius;
int k_number;
int pf_num = 0;
cout << "input radius/k_nubmer of fpfh_search: ";
//cin >> radius;
cin >> k_number;
clock_t start, finish;
start = clock();
pcl::FPFHEstimation<pcl::PointXYZ, pcl::Normal, pcl::FPFHSignature33> fpfh;
fpfh.setInputCloud(cloud_origin);
fpfh.setInputNormals(cloud_normals);
pcl::search::KdTree<pcl::PointXYZ>::Ptr tree(new pcl::search::KdTree<pcl::PointXYZ>());
fpfh.setSearchMethod(tree);
pcl::PointCloud<pcl::FPFHSignature33>::Ptr fpfh_fe_ptr(new pcl::PointCloud<pcl::FPFHSignature33>());
//pfh.setRadiusSearch(radius);
fpfh.setKSearch(k_number);
fpfh.compute(*fpfh_fe_ptr);
pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud_b(new pcl::PointCloud<pcl::PointXYZRGB>);
cloud_b->resize(cloud_origin->size());
for (int i = 0; i < cloud_origin->points.size(); i++)
{
cloud_b->points[i].x = cloud_origin->points[i].x;
cloud_b->points[i].y = cloud_origin->points[i].y;
cloud_b->points[i].z = cloud_origin->points[i].z;
}
Eigen::Vector3d d, n1, n2;
double d_x, d_y, d_z;
for (int i = 0; i < fpfh_fe_ptr->points.size(); i++)
{
if (fpfh_fe_ptr->points[i].histogram[16] < 50)
{
pf_num++;
cloud_b->at(i).r = 255;
cloud_b->at(i).g = 0;
cloud_b->at(i).b = 0;
}
else
{
cloud_b->at(i).r = 130;
cloud_b->at(i).g = 130;
cloud_b->at(i).b = 130;
}
}
finish = clock();
cout << "total time is: " << finish - start << endl;
cout << "pf_num is: " << pf_num << endl;
pcl::PCDWriter writer;
writer.write("d://sunyu.pcd", *cloud_b, false);//将点保存到PCD文件中去
//savefile(cloud_b, cloud_normals, "sunyu.ply", "FPFH");
return cloud_b;
}
int main()
{
pcl::PointCloud<pcl::Normal>::Ptr cloud_normals(new pcl::PointCloud<pcl::Normal>);
pcl::PointCloud<pcl::PointXYZ>::Ptr cloudOrigin(new pcl::PointCloud<pcl::PointXYZ>);
if (pcl::io::loadPCDFile<pcl::PointXYZ>("d://1.pcd", *cloudOrigin) == -1) //* 读入PCD格式的文件,如果文件不存在,返回-1
{
PCL_ERROR("Couldn't read file test_pcd.pcd \n"); //文件不存在时,返回错误,终止程序。
return (-1);
}
//点云滤波
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_filltered(new pcl::PointCloud<pcl::PointXYZ>);
pcl::VoxelGrid<pcl::PointXYZ> sor;
sor.setInputCloud(cloudOrigin);
sor.setLeafSize(0.01f, 0.01f, 0.01f);
sor.filter(*cloud_filltered);
cout << cloud_filltered->size() << endl;
//点云的法线
pcl::NormalEstimation<pcl::PointXYZ, pcl::Normal> ne;
ne.setInputCloud(cloud_filltered);
ne.setSearchSurface(cloudOrigin);
pcl::search::KdTree<pcl::PointXYZ>::Ptr tree(new pcl::search::KdTree<pcl::PointXYZ>());
ne.setSearchMethod(tree);
ne.setRadiusSearch(0.03);
ne.compute(*cloud_normals);
cout << cloud_filltered->size() << endl;
computeFPFH(cloudOrigin, cloud_normals);
return 0;
}
参考资料
https://blog.csdn.net/McQueen_LT/article/details/107506368?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522164907067016781683941987%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fall.%2522%257D&request_id=164907067016781683941987&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2allfirst_rank_ecpm_v1~rank_v31_ecpm-1-107506368.142v5control,157v4control&utm_term=%E5%88%A9%E7%94%A8FPFH%E8%BF%9B%E8%A1%8C%E7%89%B9%E5%BE%81%E7%82%B9%E6%8F%90%E5%8F%96&spm=1018.2226.3001.4187