使用PCL

时间:2019-06-30 23:33:24

标签: c++ point-cloud-library point-clouds normals

我正在尝试根据给定的网格,相机姿势和相机内部特性生成法线贴图。

我的计划是计算云中每个点的顶点法线,然后将它们投影到具有相应相机姿态和内在函数的图像平面上。更具体地说,我将首先计算顶点法线,然后将点坐标从世界坐标转换为具有相机姿态的相机坐标。最后,使用相机的内在函数,可以将点云投影到图像上,其中每个像素代表相应3D顶点的表面法线。

下面是我的代码:

#include <iostream>
#include <thread>
#include <pcl/io/ply_io.h>
#include <pcl/point_types.h>
#include <pcl/features/from_meshes.h>
#include <pcl/visualization/pcl_visualizer.h>

using namespace std;
using namespace pcl;

void readPLY(PolygonMesh::Ptr mesh, string fname, bool printResult=false)
{
    PLYReader reader;
    int success = reader.read(fname, *mesh); // load the file
    if (success == -1) {
        cout << "Couldn't read file " << fname << endl;
        exit(-1);
    }

    if(printResult){
        cout << "Loaded "
        << mesh->cloud.width * mesh->cloud.height
        << " data points from "
        << fname
        << " with the following fields: "
        << endl;

        // convert from pcl/PCLPointCloud2 to pcl::PointCloud<T>
        PointCloud<PointXYZ>::Ptr cloud (new PointCloud<PointXYZ>);
        fromPCLPointCloud2(mesh->cloud, *cloud);

        // print the first 10 vertices
        cout << "Vertices:" << endl;
        for (size_t i=0; i<10; ++i)
            cout << "    " << cloud->points[i].x
            << " "    << cloud->points[i].y
            << " "    << cloud->points[i].z << endl;

        // print the first 10 polygons
        cout << "Polygons:" << endl;
        for (size_t i=0; i<10; ++i){
            cout << mesh->polygons[i] << endl;
        }
    }
}

void computeNormal(PolygonMesh::Ptr mesh,
                   PointCloud<Normal>::Ptr normal,
                   bool printResult=false)
{
    // convert from pcl/PCLPointCloud2 to pcl::PointCloud<T>
    PointCloud<PointXYZ>::Ptr cloud (new PointCloud<PointXYZ>);
    fromPCLPointCloud2(mesh->cloud, *cloud);

    // compute surface normal
    pcl::features::computeApproximateNormals(*cloud, mesh->polygons, *normal);

    // print results
    if (printResult){
        cout << "Normal cloud contains "
             << normal->width * normal->height
             << " points" << endl;

         // print the first 10 vertices
         cout << "Vertex normals:" << endl;
         for (size_t i=0; i<10; ++i)
             cout << "    " << normal->points[i] << endl;
    }
}


int main (int argc, char** argv)
{
    // ./main [path/to/ply] (--debug)
    string fname = argv[1];

    // check if debug flag is set
    bool debug = false;
    for(int i=0;i<argc;++i){
        string arg = argv[i];
        if(arg == "--debug")
            debug = true;
    }

    // read file
    PolygonMesh::Ptr mesh (new PolygonMesh);
    readPLY(mesh, fname, debug);

    // calculate normals
    PointCloud<Normal>::Ptr normal (new PointCloud<Normal>);
    computeNormal(mesh, normal, debug);
}

目前,我已经使用pcl::features::computeApproximateNormals获得了每个顶点的表面法线。是否可以使用PCL将法线投影到图像平面上,并将法线的xyz元素映射到RGB通道并将图像保存到文件中?

1 个答案:

答案 0 :(得分:1)

欢迎使用堆栈溢出。文档说的是:

  

给定一个几何表面,通常推论该表面上某个点的法线方向为垂直于该点表面的向量。

根据我的发言,我得出的结论是,您已经具有可以轻松计算表面法线的表面。使用正常估算是因为3D点云数据基本上是来自现实世界的一堆采样点。您没有此类数据中的表面信息。您要做的是使用“平面拟合(2D回归)”估算像素周围的表面。然后,您获得表面法线。您无法比较这两种方法。他们本质上给出了不同的目的。

对于第二个问题:是的。请参阅this SO answer