PCL 計算點雲法向量並顯示


運用PCL計算點雲的法向量並顯示,其理論介紹在《點雲庫PCL從入門到精通》書中講的十分詳細。可以參考PCL估計點雲的表面法向量

一、法向量定向的理解:

在這裏插入圖片描述
在這裏插入圖片描述

二、pcl::Normal的定義

compute(*normal)裏計算出來的結果是:法向量的x,y,z座標和表面曲率curvature。其內部結構爲:

 /*brief A point structure representing normal coordinates and the surface curvature estimate. (SSE friendly)ingroup common*/

struct Normal : public _Normal
{
    inline Normal (const _Normal &p)
    {
     normal_x = p.normal_x; 
     normal_y = p.normal_y; 
     normal_z = p.normal_z;
     data_n[3] = 0.0f;
     curvature = p.curvature;
    }

    inline Normal ()
    {
     normal_x = normal_y = normal_z = data_n[3] = 0.0f;
     curvature = 0;
    }

    inline Normal (float n_x, float n_y, float n_z)
    {
     normal_x = n_x; normal_y = n_y; normal_z = n_z;
     curvature = 0;
     data_n[3] = 0.0f;
    }

    friend std::ostream& operator << (std::ostream& os, const Normal& p);
    EIGEN_MAKE_ALIGNED_OPERATOR_NEW
};


三、pcl::Normal的幾種輸出方式:

          cout<<normals->points[0]<<endl;
     cout<<"["<<normals->points[0].normal_x<<" "
              <<normals->points[0].normal_y<<" "
              <<normals->points[0].normal_z<<" "
              <<normals->points[0].curvature<<"]"<<endl;

     cout<<"["<<normals->points[0].normal[0]<<" "
              <<normals->points[0].normal[1]<<" "
              <<normals->points[0].normal[2]<<" "
              <<normals->points[0].curvature<<"]"<<endl;

     cout<<"["<<normals->points[0].data_n[0]<<" "
              <<normals->points[0].data_n[1]<<" "
              <<normals->points[0].data_n[2]<<" "
              <<normals->points[0].curvature<<"]"<<endl;

四、計算法線並顯示:

#include <pcl/point_types.h>
#include <pcl/io/pcd_io.h>
#include <pcl/kdtree/kdtree_flann.h>
#include <pcl/features/normal_3d.h>
#include <pcl/surface/gp3.h>
#include <pcl/visualization/pcl_visualizer.h>
#include <boost/thread/thread.hpp>
#include <pcl/features/normal_3d_omp.h>//使用OMP需要添加的頭文件
using namespace std;
int main()
{
	//加載點雲數據
	pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);
	if (pcl::io::loadPCDFile<pcl::PointXYZ>("horse.pcd", *cloud) == -1)
	{
		PCL_ERROR("Could not read file\n");
	}

	//計算法線
	pcl::NormalEstimationOMP<pcl::PointXYZ, pcl::Normal> n;//OMP加速
	pcl::PointCloud<pcl::Normal>::Ptr normals(new pcl::PointCloud<pcl::Normal>);
	//建立kdtree來進行近鄰點集搜索
	pcl::search::KdTree<pcl::PointXYZ>::Ptr tree(new pcl::search::KdTree<pcl::PointXYZ>);
	//爲kdtree添加點雲數據
	//tree->setInputCloud(cloud);
	n.setNumberOfThreads(10);//設置openMP的線程數
	//n.setViewPoint(0,0,0);//設置視點,默認爲(0,0,0)
	n.setInputCloud(cloud);
	n.setSearchMethod(tree);
	n.setKSearch(10);//點雲法向計算時,需要所搜的近鄰點大小
	//n.setRadiusSearch(0.03);//半徑搜素
	n.compute(*normals);//開始進行法向計
	
	/*圖形顯示*/
	boost::shared_ptr<pcl::visualization::PCLVisualizer> viewer(new pcl::visualization::PCLVisualizer("3D viewer"));
	//viewer->initCameraParameters();//設置照相機參數,使用戶從默認的角度和方向觀察點雲
	//設置背景顏色
	viewer->setBackgroundColor(0.3, 0.3, 0.3);
	viewer->addText("faxian", 10, 10, "text");
	
	//設置點雲顏色
	pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> single_color(cloud, 0, 225, 0);
	//添加座標系
	viewer->addCoordinateSystem(0.1);
	viewer->addPointCloud<pcl::PointXYZ>(cloud, single_color, "sample cloud");
	viewer->addPointCloudNormals<pcl::PointXYZ, pcl::Normal>(cloud, normals, 20, 0.02, "normals");
	//設置點雲大小
	viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 2, "sample cloud");
	while (!viewer->wasStopped())
	{
		viewer->spinOnce(100);
		boost::this_thread::sleep(boost::posix_time::microseconds(100000));
	}

	return 0;
}

五、使用OMP的報錯處理

在應用OpenMP,可能會報錯“User Error 1001: argument to num_threads clause must be positive”。這是由於設置的線程數必須爲正,而程序中可能沒有設置,有時候甚至環境變量中設置了,但是依然報錯,手動設置如下:

n.setNumberOfThreads(4);  // 手動設置線程數,比源碼增加,否則提示錯誤

六、PCL::Normal官網鏈接

pcl::NormalEstimation

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章