如何使用PCL将XYZRGB点云转换为彩色mesh模型

2023-11-20

如何使用PCL将XYZRGB点云转换为彩色mesh模型

最近完成了一个使用RGBD传感器,构建物体模型的小demo。其中有点难的最后一步是如何将获得的物体点云变成彩色mesh模型。效果图如下(从点云变成彩色mesh):
原点云
彩色mesh
其实整体的步骤可以总结如下:
[1]计算点云法向,并将法向量指向内部
[2]将点云法向信息叠加在原点云上,生成pcl::PointXYZRGBNormal格式的点云
[3]使用泊松重建(poisson reconstruction)建立无颜色mesh。
[4]使用kdtree将原点云的信息映射在无颜色mesh上,并生成彩色mesh。


下面具体介绍一下各步骤:
[1]计算点云法向
使用pcl::NormalEstimationOMP设定法向估算对象。这里使用的算法实质上是主成分分析(PCA)。先设定每个点周围选取的临近点数和搜索半径,并用临近点建立一个协方差矩阵C。
这里写图片描述
这里K指的是离点P的最近的K个点,是最近邻的中心。后面的式子就是特征值和特征向量了。而C的最小特征值对应的特征向量就是该点的法向量。
但是泊松重建需要的是指向物体内部的法向量,所以我们还要将向量反转过来。

[2]将点云法向信息叠加在原点云上,生成pcl::PointXYZRGBNormal格式的点云
这一步比较简单,使用的是pcl::concatenateFields,可以将两种不同格式的点云组合起来。

[3]使用泊松重建(poisson reconstruction)建立无颜色mesh。
泊松重建的原理比较复杂,我也没有完全弄清楚。先留下这个坑,以后清楚了再填。大致的算法如下:
1、为点云设定八叉树搜索索引,使得每个采样点都落在深度为D的叶节点。
2、设定函数空间。
3、创建向量场。这一步我理解就是用到了之前算出的法向量。
4、求解泊松方程。
5、提取等值面,从而得到重建表面。
pcl中对应的是pcl::Poisson可以设定泊松处理对象。但是泊松重建后生成的mesh是没有RGB信息的。目前,PCL官方也说泊松重建不带有颜色信息,需要我们自己添加。

[4]使用kdtree将原点云的信息映射在无颜色mesh上,并生成彩色mesh。
这一步在网上基本找不到信息,所以我研究了一下。最终还是在一个user mailing的回答里得到了启发。我们可以使用kd tree在原RGB点云上建立一个搜索索引,然后对mesh上的每一个点都搜索对应原RGB点云上的临近点。然后求得这些对应临近点的RGB通道均值,作为mesh上那个点的颜色信息就好了。
这里值得注意的是两个转换函数pcl::fromPCLPointCloud2pcl::toPCLPointCloud2,其作用分别是将mesh的信息转为点云和将点云信息转进mesh。

最后,就放一下源码啦。


void poisson_reconstruction(pcl::PointCloud<pcl::PointXYZRGBA>::Ptr object_cloud)
{
      PointCloud<PointXYZRGB>::Ptr cloud(new PointCloud<PointXYZRGB>());
      pcl::copyPointCloud(*object_cloud, *cloud);
      PointCloud<PointXYZRGB>::Ptr filtered(new PointCloud<PointXYZRGB>());
      PassThrough<PointXYZRGB> filter;
      filter.setInputCloud(cloud);
      filter.filter(*filtered);
      cout << "passthrough filter complete" << endl;

      cout << "begin normal estimation" << endl;
      NormalEstimationOMP<PointXYZRGB, Normal> ne;//计算点云法向
      ne.setNumberOfThreads(8);//设定临近点
      ne.setInputCloud(filtered);
      ne.setRadiusSearch(0.01);//设定搜索半径
      Eigen::Vector4f centroid;
      compute3DCentroid(*filtered, centroid);//计算点云中心
      ne.setViewPoint(centroid[0], centroid[1], centroid[2]);//将向量计算原点置于点云中心

      PointCloud<Normal>::Ptr cloud_normals (new PointCloud<Normal>());
      ne.compute(*cloud_normals);
      cout << "normal estimation complete" << endl;
      cout << "reverse normals' direction" << endl;

//将法向量反向
      for(size_t i = 0; i < cloud_normals->size(); ++i)
      {
        cloud_normals->points[i].normal_x *= -1;
        cloud_normals->points[i].normal_y *= -1;
        cloud_normals->points[i].normal_z *= -1;
      }

//融合RGB点云和法向
      cout << "combine points and normals" << endl;
      PointCloud<PointXYZRGBNormal>::Ptr cloud_smoothed_normals(new PointCloud<PointXYZRGBNormal>());
      concatenateFields(*filtered, *cloud_normals, *cloud_smoothed_normals);

//泊松重建
      cout << "begin poisson reconstruction" << endl;
      Poisson<PointXYZRGBNormal> poisson;
      //poisson.setDegree(2);
      poisson.setDepth(8);
      poisson.setSolverDivide (6);
      poisson.setIsoDivide (6);

      poisson.setConfidence(false); 
      poisson.setManifold(false); 
      poisson.setOutputPolygons(false); 

      poisson.setInputCloud(cloud_smoothed_normals);
      PolygonMesh mesh;
      poisson.reconstruct(mesh);

      cout << "finish poisson reconstruction" << endl;

//给mesh染色
      PointCloud<PointXYZRGB> cloud_color_mesh; 
      pcl::fromPCLPointCloud2(mesh.cloud, cloud_color_mesh); 

      pcl::KdTreeFLANN<pcl::PointXYZRGB> kdtree;
      kdtree.setInputCloud (cloud);
      // K nearest neighbor search
      int K = 5;
      std::vector<int> pointIdxNKNSearch(K);
      std::vector<float> pointNKNSquaredDistance(K);
      for(int i=0;i<cloud_color_mesh.points.size();++i)
      {
         uint8_t r = 0;
         uint8_t g = 0;
         uint8_t b = 0;
         float dist = 0.0; 
         int red = 0;
         int green = 0;
         int blue = 0;
         uint32_t rgb;

         if ( kdtree.nearestKSearch (cloud_color_mesh.points[i], K, pointIdxNKNSearch, pointNKNSquaredDistance) > 0 )
         {
            for (int j = 0; j < pointIdxNKNSearch.size (); ++j) 
            { 

               r = cloud->points[ pointIdxNKNSearch[j] ].r;
               g = cloud->points[ pointIdxNKNSearch[j] ].g;
               b = cloud->points[ pointIdxNKNSearch[j] ].b;

               red += int(r);
               green += int(g);
               blue += int(b);
               dist += 1.0/pointNKNSquaredDistance[j]; 

               std::cout<<"red: "<<int(r)<<std::endl; 
               std::cout<<"green: "<<int(g)<<std::endl; 
               std::cout<<"blue: "<<int(b)<<std::endl; 
               cout<<"dis:"<<dist<<endl;
            }  
         }

         cloud_color_mesh.points[i].r = int(red/pointIdxNKNSearch.size ()+0.5); 
         cloud_color_mesh.points[i].g = int(green/pointIdxNKNSearch.size ()+0.5); 
         cloud_color_mesh.points[i].b = int(blue/pointIdxNKNSearch.size ()+0.5);


      }
      toPCLPointCloud2(cloud_color_mesh, mesh.cloud);
      io::savePLYFile("/home/xxx/3d_model_building/src/make_model/result/object_mesh.ply", mesh);
}

如有问题,还请大家指出。


参考资料:
[1]http://blog.csdn.net/qq_25491201/article/details/51100073
[2]http://blog.csdn.net/jennychenhit/article/details/52126156?locationNum=8
[3]https://wenku.baidu.com/view/23c5637a31b765ce050814d2.html

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何使用PCL将XYZRGB点云转换为彩色mesh模型 的相关文章

  • PCL调错:合集

    1 error C4996 pcl visualization PointCloudColorHandler
  • 两种点云分割(一)— RANSAC分割平面

    本文为博主原创文章 未经博主允许不得转载 本文为专栏 python三维点云从基础到深度学习 系列文章 地址为 https blog csdn net suiyingy article details 124017716 点云分割的目的是将点
  • unity实现简单自动寻路

    unity实现简单自动寻路 1 打开unity创建一个简单的场景 如下图 2 除了场景中的两个对象将所创建的地形设置为静态 3 给主角添加Nav mesh Agent 组件 4 烘焙地图 简单来说就是烘焙自动行走的路径 要注意蓝色区域为烘焙
  • 平面离散点集Delaunay三角化

    文章目录 定义 准则 特性 算法 1 逐点插入法 2 分治算法 3 生长算法 对比 参考 定义 在数学和计算几何中 三角化就是对于给定的平面中的离散点集P 生成三角形集合T的过程 一般来说给定一个点集 往往存在不止一个三角剖分 其中基于 D
  • BLE MESH在配网广播中的Service UUID:1827与1828

    Mesh Provisioning UUID 1827 是一种服务的UUID 一般在广播包中中代表设备为未配网设备 也用于给配网器进行识别 在该服务下还有两个UUID 0x2ADB 用于写 0x2ADC 用于上报 在使用GATT配网阶段的数
  • 【3D点云】分割算法总结(一)

    文章目录 前言 Related work 一 PointNet 分类 分割2018 1 关键代码 1 点云采样 2 卷积下采样 升维 3 上采样 self fp4 l3 xyz l4 xyz l3 points l4 points 二 MV
  • PCL调错:(3)error C2589“(“:“::“右边的非法标记

    错误提示 造成该错误的原因是 pcl库中的函数模板max与Visual C 中的全局的宏max冲突 百度了以下看了一共有两种解决方案 第一种不用修改库里边的源代码 设置项目属性 在预定义处理器中添加定义NOMINMAX来禁止使用Visual
  • NumPy 中网格的用途是什么?

    目的是什么np meshgrid 我知道它创建了某种用于绘图的坐标网格 但我看不到它的直接好处 官方文档给出了以下示例 但其输出对我来说没有意义 x np arange 5 5 1 y np arange 5 5 1 xx yy np me
  • 团结| mesh.colors 不会为我的自定义网格对象着色

    我在 Unity 中构建了一个自定义金字塔 如下所示 Mesh mesh GetComponent
  • 我可以从网格生成点云吗? [关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 我正在尝试从网格生成点云数据 例如 Maya 的 obj 文件 但是 我只能在互联网上找到相反的情况
  • 在python中使用VTK找到3D空间中两个圆柱体的交集

    在 python 中使用 VTK 我编写了一些代码来为我想要的对象创建一个 actor 例如对于气缸 def cylinder object startPoint endPoint radius my color DarkRed USER
  • 我可以在 Three.js 中隐藏网格的面吗?

    我想使网格的某些部分在运行时不可见 我可以将这些部分设置为不可见 透明吗 通过改变单个面孔的属性 网格本身仅使用一种材料 示例说明 as the editor理解这个问题 想象一个网格 这里有 20 个顶点的几何图形 其中每个四个顶点的四边
  • 四边形网格划分库

    我试图找到一个用 C 编写的网格划分库 仅使用四边形网格对自定义形状进行网格划分 这是我正在寻找的算法 代码的示例 但这不是免费的并且是用 ANSI C 编写的 http members ozemail com au comecau qua
  • Three.js 加载已三角化的网格是否比使用四边形的网格性能更高?

    我读过 Three js 对所有网格面进行三角剖分 这是正确的吗 然后我意识到我使用的大多数 gltf 模型都有四面体 在 Blender 中对面进行三角测量非常容易 所以我很好奇对面进行预先三角测量是否会导致网格加载更快 提前致谢 如果您
  • 表面网格到体积网格

    我有一个使用 Meshlab 从点云生成的封闭表面网格 我需要为此获得一个体积网格 这样它就不是一个空心物体 我想不通 我需要获取 stl 文件进行打印 谁能帮我获得体积网格 我更喜欢简单的解决方案而不是复杂的算法 给定一个定向的水密表面网
  • MATLAB:在子图中绘制/保存网格函数的 X-Y 视图

    正如标题所示 我试图将网格函数的 2 变量切片 例如 作为 jpg 保存为子图 我想使用 m 文件来执行此操作 因为我有很多要生成的图 我已经弄清楚如何在他们自己的图形上绘制视图 但我无法让它们正确地绘制为图形中的子图 为了说明我的意思 以
  • 环境错误:Gmsh 版本必须 >= 2.0

    我是 fipy 的新手 所以如果我问一些应该显而易见的问题 请原谅我的无知 但我无法运行已经存在的 并且在其他机器上工作的 脚本 无法获取EnvironmentError Gmsh version must be gt 2 0 我可能在安装
  • Unity3D 带孔动态网格

    从两个顶点列表动态创建一个带有孔的网格 我目前正在尝试动态创建一个带有孔的网格 2D 我有一个轮廓和孔轮廓的 Vector3 顶点列表 我的问题 How would I go about merging these two lists of
  • Unity:将网格物体轻轻包裹在其他网格物体周围?

    给定一个网格 如左侧的立方体对象 和另一个自定义的球状网格 右侧 如果更容易的话 它可以是另一种形状 Unity 和 C 中的一个在运行时如何将第二个网格轻轻包裹在第一个网格周围 谢谢 下面的方法 借助 VirtualMethodStudi
  • 在 Three.js 中使用多种材质来合并几何体

    我想使用 2 个网格创建一棵松树 其中 1 个用于树干 另一个用于灌木 这就是我所做的 var pine geometry new THREE Geometry var pine texture 1 THREE ImageUtils loa

随机推荐

  • CrimeKgAssitant-master的案件分类模块思路整理(多标签分类模型)

    根据liuhuanyong模型改动 尝试推广到其它领域 原始模型连接 GitHub liuhuanyong CrimeKgAssitant Crime assistant including crime type prediction an
  • TOOLS_Pandas根据日期列进行分组统计及绘图的使用示例

    Pandas根据日期列进行分组统计及绘图的使用示例 导入所需要的库 coding utf 8 from logging import warning import os sys import datetime import numpy as
  • linux端口被占用,netstat查看无进程号,端口状态一直停留在FIN_WAIT1以及CLOSE_WAIT状态

    环境信息 CentOS 6 5 现象 同事启动程序发现端口被占用 netstat查看之后发现如下现象 发现端口处于FIN WAIT1状态以及CLOSE WAIT状态 无法释放 问题分析 FIN WAIT1以及CLOSE WAIT状态的原理以
  • 如何通过电脑向ipad传电影视频(不用越狱)

    前言 为了能在ipad上看电脑上已下载的电影 我可是试了各种方法 心好累 还好终于解决了 不得不说 网上没一个靠谱的答案 方法一 如果电影本身的格式是 mp4 mov m4a格式 通过官方的itunes软件 直接导入媒体库 然后在ipad上
  • 聚宽源码17

    原文策略源码如下 导入函数库 from jqdata import import talib from math import isnan def initialize context 设置参数 set parameter context
  • React实现关键字高亮

    先看效果 实现很简单通过以下这个函数 highLight text keyword gt return text split keyword flatMap str gt span keyword span str slice 1 展示某段
  • SQLite3 获取最小可用ID,ID无需包含1

    SQLite3 获取最小可用ID ID无需包含1 一 语法 二 解析 1 判断最小ID是否为1 2 判断最小ID递增后是否存在 3 范围限定 三 总结 一 语法 获取1 到 500 范围间的最小可用ID select CASE WHEN s
  • Visual Studio 2017无法登录问题解决

    前两天登录VS2017的时候遇到无法登录问题 截图如下 期间试了各种方法 更新重启 添加一系列站点至信任域等等 还是没有效果 同时突然想起来自己的IE浏览器一直无法正常上网 不确定和VS无法登录是否有一定的联系 抱着试试看的心态上网搜索了一
  • IGWO-SVM:改良的灰狼优化算法改进支持向量机。 采用三种改进思路:两种Logistic和Tent混沌映射和采用DIH策略

    IGWO SVM 改良的灰狼优化算法改进支持向量机 采用三种改进思路 两种Logistic和Tent混沌映射和采用DIH策略 采用基于DIH维度学习的狩猎搜索策略为每只狼构建邻域 增强局部和全局搜索能力 收敛速度比GWO更快 适用于pape
  • 工控安全PLC固件逆向三

    之前我们详细分析了bootram和Vxworks的基本启动流程 这篇文章中我们把视线转到plc的网络部分 同时来复现我们第一个 第二个工控安全漏洞 一 VxWorks的网络设备驱动 一般我们说有三种设备 块设备 字符设备 网络设备 但是考虑
  • 【封装】实体类(entity)

    实体类entity 一 ORM 1 1 ORM 实体类 entity 零散数据的载体 1 1 1 ORM应用 一 ORM ORM Object Relational Mapping 从数据库查询到的结果集 ResultSet 在进行遍历时
  • Error while parsing UI hierarchy XML file: Invalid ui automator hierarchy file. Error while parsing

    官方的工具就这吊样各种报错 不如使用二次开发的工具 使用 https github com alibaba web editor 替代
  • el-select实现懒加载

    先看一个线上的演示示例 https code juejin cn pen 7273352811440504889 背景 我们在实际开发中经常遇到这样的需求 el select实现懒加载 用通俗的话说 为了增加响应速度 就是初始下拉只展示50
  • 网络流量在线分析系统的设计与实现

    编译环境 visual studio2019 安装并配置winpcap和pthreads库函数 1 配置环境 1 1 安装vscode 参考微信公众号 软件安装管家 1 2 安装MinGW w64 下载地址 添加链接描述 安装参考博客 Mi
  • 实验二 程序流程控制

    1 编写程序计算 1 3 5 7 99 之和 summ 0 for i in range 1 100 summ summ i print 和为 summ 2 编写程序 计算 2 4 6 8 100 之和 summ 0 for i in ra
  • 计算机网络试题

    一 选择题 1 OSI模型与TCP IP模型都具有的层次是 A 会话层 网络层和物理层 B 表示层 会话层和数据链路层 C 网络层 传输层和应用层 D 表示层 数据链路层和物理层 2 对于计算机网络体系结构 下列关于第N层和第N 1层的关系
  • 蓝桥杯:字符串

    题目链接 include
  • notepad++字符串替换

    删除空白行 在编辑选项里面包括很多功能 编辑 gt 行操作 gt 移除空行 包括空白字符 行首添加字符串 按CTRL F 选择替换页签 选择正则表达式 查找目标 设置为 替换为 设置自己想要替换的字符串 特殊字符需要添加 进行转义 行尾添加
  • 【MySQL】34道SQL综合练习详解(员工表、部门表、工资等级表)

    文章目录 一 34道SQL综合练习 二 测试使用的数据表 三 创建测试表的SQL语句 一 34道SQL综合练习 1 查询取得每个部门最高工资的人员信息 select e ename t from emp e join select dept
  • 如何使用PCL将XYZRGB点云转换为彩色mesh模型

    如何使用PCL将XYZRGB点云转换为彩色mesh模型 最近完成了一个使用RGBD传感器 构建物体模型的小demo 其中有点难的最后一步是如何将获得的物体点云变成彩色mesh模型 效果图如下 从点云变成彩色mesh 其实整体的步骤可以总结如