我正在尝试根据给定的网格,相机姿势和相机内部特性生成法线贴图。
我的计划是计算云中每个点的顶点法线,然后将它们投影到具有相应相机姿态和内在函数的图像平面上。更具体地说,我将首先计算顶点法线,然后将点坐标从世界坐标转换为具有相机姿态的相机坐标。最后,使用相机的内在函数,可以将点云投影到图像上,其中每个像素代表相应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通道并将图像保存到文件中?
答案 0 :(得分:1)
欢迎使用堆栈溢出。文档说的是:
给定一个几何表面,通常推论该表面上某个点的法线方向为垂直于该点表面的向量。
根据我的发言,我得出的结论是,您已经具有可以轻松计算表面法线的表面。使用正常估算是因为3D点云数据基本上是来自现实世界的一堆采样点。您没有此类数据中的表面信息。您要做的是使用“平面拟合(2D回归)”估算像素周围的表面。然后,您获得表面法线。您无法比较这两种方法。他们本质上给出了不同的目的。
对于第二个问题:是的。请参阅this SO answer。