PCL中计算点云的法向量并显示

参考源:http://www.cnblogs.com/bozhicheng/p/5842428.html
利用的是最小二乘估计的方法计算了点云的法向量,并且提供了两种法线的显示方法,还设置了多个ViewPort,练习了点云的显示:

// NormalEstimation.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#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>


int main()
{
    //加载点云模型
    pcl::PointCloud<pcl::PointXYZ>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZ>);

    if (pcl::io::loadPCDFile<pcl::PointXYZ>("D:\\rabbit.pcd", *cloud)==-1)
    {
        PCL_ERROR("Could not read file\n");
    }

    //计算法线
    pcl::NormalEstimation<pcl::PointXYZ, pcl::Normal> n;
    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.setInputCloud(cloud);
    n.setSearchMethod(tree);
    //点云法向计算时,需要所搜的近邻点大小
    n.setKSearch(20);
    //开始进行法向计算
    n.compute(*normals);

    /*图形显示模块*/
    boost::shared_ptr<pcl::visualization::PCLVisualizer> viewer(new pcl::visualization::PCLVisualizer("3D viewer"));
    //viewer->initCameraParameters();

    int v1(0), v2(1),v3(2),v4(3);
    viewer->createViewPort(0.0, 0.0, 0.5, 0.5, v1);
    viewer->createViewPort(0.5, 0.0, 1.0, 0.5, v2);
    viewer->createViewPort(0.0, 0.5, 0.5, 1.0, v3);
    viewer->createViewPort(0.5, 0.5, 1.0, 1.0, v4);

    //设置背景颜色
    viewer->setBackgroundColor(5,55, 10, v1);
    //设置点云颜色
    pcl::visualization::PointCloudColorHandlerCustom<pcl::PointXYZ> single_color(cloud, 0, 225, 0);
    //添加坐标系
    viewer->addCoordinateSystem(0.5, v1);

    viewer->addPointCloud<pcl::PointXYZ>(cloud, "sample cloud",v1);
    viewer->addPointCloud<pcl::PointXYZ>(cloud, "sample cloud0", v2);
    viewer->addPointCloudNormals<pcl::PointXYZ, pcl::Normal>(cloud, normals, 50, 0.01, "normals",v2);
    viewer->addPointCloud<pcl::PointXYZ>(cloud, single_color, "sample cloud1", v3);
    viewer->addPointCloud<pcl::PointXYZ>(cloud, "sample cloud3", v4);

    //设置点云大小
    viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 2, "sample cloud3", 4);


    //添加点云法向量的另一种方式;
    //解决来源http://www.pcl-users.org/How-to-add-PointNormal-on-PCLVisualizer-td4037041.html
    //pcl::PointCloud<pcl::PointNormal>::Ptr cloud_with_normals(new pcl::PointCloud<pcl::PointNormal>);
    //pcl::concatenateFields(*cloud, *normals, *cloud_with_normals);
    //viewer->addPointCloudNormals<pcl::PointNormal>(cloud_with_normals, 50, 0.01, "normals");
    //
    while (!viewer->wasStopped())
    {
        viewer->spinOnce(100);
        boost::this_thread::sleep(boost::posix_time::microseconds(100000));
    }

    return 0;
}
  • 4
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
计算点云向量可以使用PCL库的NormalEstimation类。 首先,需要对点云进行下采样,以减少计算量和噪声对向量的影响。可以使用VoxelGrid滤波器实现。 然后,需要创建一个NormalEstimation对象,并将下采样后的点云数据传递给它。接着,可以设置线估计方的搜索半径,并调用compute()方计算向量。 最后,可以使用PassThrough滤波器过滤掉无效向量。例如,可以通过设置向量的z值是否为nan来实现。 下面是一段示例代码: ```cpp #include <pcl/io/pcd_io.h> #include <pcl/point_types.h> #include <pcl/filters/voxel_grid.h> #include <pcl/features/normal_3d.h> #include <pcl/filters/passthrough.h> int main (int argc, char** argv) { // 加载点云数据 pcl::PointCloud<pcl::PointXYZ>::Ptr cloud (new pcl::PointCloud<pcl::PointXYZ>); pcl::io::loadPCDFile<pcl::PointXYZ> ("input.pcd", *cloud); // 下采样 pcl::VoxelGrid<pcl::PointXYZ> sor; sor.setInputCloud (cloud); sor.setLeafSize (0.01f, 0.01f, 0.01f); sor.filter (*cloud); // 计算向量 pcl::NormalEstimation<pcl::PointXYZ, pcl::Normal> ne; ne.setInputCloud (cloud); pcl::search::KdTree<pcl::PointXYZ>::Ptr tree (new pcl::search::KdTree<pcl::PointXYZ>); ne.setSearchMethod (tree); pcl::PointCloud<pcl::Normal>::Ptr cloud_normals (new pcl::PointCloud<pcl::Normal>); ne.setRadiusSearch (0.03); ne.compute (*cloud_normals); // 过滤无效向量 pcl::PassThrough<pcl::Normal> pass; pass.setInputCloud (cloud_normals); pass.setFilterFieldName ("normal_z"); pass.setFilterLimits (-1.0, 1.0); pcl::PointCloud<pcl::Normal>::Ptr cloud_normals_filtered (new pcl::PointCloud<pcl::Normal>); pass.filter (*cloud_normals_filtered); // 输出结果 pcl::io::savePCDFileASCII ("output.pcd", *cloud_normals_filtered); return 0; } ``` 其,setRadiusSearch()方用于设置搜索半径。这个半径越大,计算出的向量越平滑;反之,则越精细。 PassThrough滤波器的setFilterFieldName()方用于设置过滤字段,这里设置为normal_z,表示对向量的z值进行过滤。setFilterLimits()方用于设置过滤范围,这里设置为(-1.0, 1.0),表示只保留z值在这个范围内的向量

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值