点云素材:bunny.txt
#include <pcl/features/normal_3d.h>
#include <pcl/visualization/pcl_visualizer.h>
void CreateCloudFromTxt(const std::string& file_path,
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud) {
std::ifstream fin(file_path.c_str());
std::string line;
pcl::PointXYZ point;
while (getline(fin, line)) {
std::stringstream ss(line);
ss >> point.x;
ss >> point.y;
ss >> point.z;
cloud->push_back(point);
}
fin.close();
}
void EstimateNormal(const pcl::PointCloud<pcl::PointXYZ>::Ptr cloud,
pcl::PointCloud<pcl::Normal>::Ptr normals) {
pcl::NormalEstimation<pcl::PointXYZ, pcl::Normal> normal_est;
normal_est.setInputCloud(cloud);
// normal_est.setRadiusSearch(0.05); // 对于每一个点都用半径为5cm的近邻搜索方式
normal_est.setKSearch(10); // 点云法向计算时,需要搜索的近邻点数目
pcl::search::KdTree<pcl::PointXYZ>::Ptr kdtree(new pcl::search::KdTree<pcl::PointXYZ>);
normal_est.setSearchMethod(kdtree); // 建立kdtree来进行近邻点集搜索
normal_est.compute(*normals);
}
void visualization(pcl::PointCloud<pcl::PointXYZ>::Ptr cloud,
pcl::PointCloud<pcl::Normal>::Ptr normals) {
boost::shared_ptr<pcl::visualization::PCLVisualizer> viewer(new pcl::visualization::PCLVisualizer("Normals"));
viewer->setBackgroundColor(0, 0, 0);
//按照z值进行渲染点的颜色
pcl::visualization::PointCloudColorHandlerGenericField<pcl::PointXYZ> fildColor(cloud, "x");
// 添加需要显示的点云数据
viewer->addPointCloud<pcl::PointXYZ>(cloud, fildColor, "bunny cloud");
// viewer->addPointCloud<pcl::PointXYZ>(cloud, "bunny cloud");
// 设置点显示大小
viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 3, "bunny cloud");
// 添加需要显示的点云法向。cloud为原始点云模型,normal为法向信息,1表示需要显示法向的点云间隔,即每1个点显示一次法向,0.003表示法向长度。
// viewer->addPointCloudNormals<pcl::PointXYZ, pcl::Normal>(cloud, normals, 1, 0.003, "normals");
// Concatenate the XYZ and normal fields* 将点云数据与法向信息拼接
pcl::PointCloud<pcl::PointNormal>::Ptr cloud_with_normals(new pcl::PointCloud<pcl::PointNormal>); // pcl::PointNormal, pcl::PointXYZINormal, pcl::PointXYZRGBNormal
pcl::concatenateFields(*cloud, *normals, *cloud_with_normals);
viewer->addPointCloudNormals<pcl::PointNormal>(cloud_with_normals, 1, 0.003, "normals");
while (!viewer->wasStopped()) {
viewer->spinOnce(100);
boost::this_thread::sleep(boost::posix_time::microseconds(100000));
}
}
int main(int argc,char**argv) {
// 加载点云模型
pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
CreateCloudFromTxt("/tmp/bunny.txt", cloud);
// 计算法线
pcl::PointCloud<pcl::Normal>::Ptr normals(new pcl::PointCloud<pcl::Normal>);
EstimateNormal(cloud, normals);
std::cout << "cloud size: " << cloud->size() << std::endl;
std::cout << "normals size: " << normals->size() << std::endl;
for (size_t i = 0; i < 5 && i < normals->size(); ++i) {
std::cout << "[" << normals->points.at(i).normal_x << ", " // 法线各轴分量
<< normals->points.at(i).normal_y << ", "
<< normals->points.at(i).normal_z << ", "
<< normals->points.at(i).curvature << "]" << std::endl; // 曲率
}
// 可视化点云及其法线
visualization(cloud, normals);
return 0;
}
输出:
可视化结果: