我之前有一篇博客Convert PLY to VTK Using PCL 1.6.0 or PCL 1.8.0 使用PCL库将PLY格式转为VTK格式展示了如何将PLY格式文件转化为VTK格式的文件,在文章的最后提到了VTK文件保存纹理的两种方式,第一种是需要有texture的图片,然后每个点存储上该点在图片中的x,y坐标,一般会normalize到[0,1]之间。第二种方法是直接存每个点的rgb值,上面的方法用的是第二种,因为导入的PLY格式就直接存储的texture的rgb值,并没有额外提供texture图片。

对于一般的PLY或者PCD格式的点云,一般都是用第二种方式来保存纹理的,即直接存储rgb值,这样转换成的vtk文件自然也是第二种情况,而对于大多数的可视化软件,比如ParaView或者3D Slicer,貌似只支持第一种方式,即需要导入texture图片(如果大家知道直接显示rgb值的方法,请在下方留言告知博主)。这样就极大的不方便了,而且PCL库中的点云格式一般也是XYZRGBA,并没有带UV,纹理有专门的数据结构。我们的目标是生成带texture coordinates的VTK文件,那么可以通过修改pcl自带的saveVTKFile函数来实现目标。

这里我们把纹理坐标单独抽出来,用下面的数据结构来表示:

std::vector<Eigen::Vector2f> texcoord;

pcl自带的pcl::io::saveVTKFile函数所在的文件的地址是.../io/src/vtk_io.cpp。默认的是写入RGB的值,我们只需要注释掉写入RGB的部分,添加上写入纹理坐标的部分:

Using PCL 1.6.0

// PCL 1.6.0int save_vtk_file(const std::string &file_name, const sensor_msgs::PointCloud2 &cloud, const std::vector<Eigen::Vector2f>& texcoord,unsigned precision)
{if (cloud.data.empty ()){PCL_ERROR ("[pcl::io::saveVTKFile] Input point cloud has no data!\n");return (-1);}// Open file
    std::ofstream fs;fs.precision (precision);fs.open (file_name.c_str ());unsigned int nr_points  = cloud.width * cloud.height;unsigned int point_size = static_cast<unsigned int> (cloud.data.size () / nr_points);// Write the header informationfs << "# vtk DataFile Version 3.0\nvtk output\nASCII\nDATASET POLYDATA\nPOINTS " << nr_points << " float" << std::endl;// Iterate through the pointsfor (unsigned int i = 0; i < nr_points; ++i){int xyz = 0;for (size_t d = 0; d < cloud.fields.size (); ++d){int count = cloud.fields[d].count;if (count == 0)count = 1;          // we simply cannot tolerate 0 counts (coming from older converter code)int c = 0;if ((cloud.fields[d].datatype == sensor_msgs::PointField::FLOAT32) && (cloud.fields[d].name == "x" || cloud.fields[d].name == "y" || cloud.fields[d].name == "z")){float value;memcpy (&value, &cloud.data[i * point_size + cloud.fields[d].offset + c * sizeof (float)], sizeof (float));fs << value;if (++xyz == 3)break;}fs << " ";}if (xyz != 3){PCL_ERROR ("[pcl::io::saveVTKFile] Input point cloud has no XYZ data!\n");return (-2);}fs << std::endl;}// Write verticesfs << "\nVERTICES " << nr_points << " " << 2*nr_points << std::endl;for (unsigned int i = 0; i < nr_points; ++i)fs << "1 " << i << std::endl;// Write RGB values
//     int field_index = pcl::getFieldIndex (cloud, "rgb");
//     if (field_index != -1)
//     {
//         fs << "\nPOINT_DATA " << nr_points << "\nCOLOR_SCALARS scalars 3\n";
//         for (unsigned int i = 0; i < nr_points; ++i)
//         {
//             int count = cloud.fields[field_index].count;
//             if (count == 0)
//                 count = 1;          // we simply cannot tolerate 0 counts (coming from older converter code)
//             int c = 0;
//             if (cloud.fields[field_index].datatype == sensor_msgs::PointField::FLOAT32)
//             {
//                 pcl::RGB color;
//                 memcpy (&color, &cloud.data[i * point_size + cloud.fields[field_index].offset + c * sizeof (float)], sizeof (pcl::RGB));
//                 int r = color.r;
//                 int g = color.g;
//                 int b = color.b;
//                 fs << static_cast<float> (r) / 255.0f << " " << static_cast<float> (g) / 255.0f << " " << static_cast<float> (b) / 255.0f;
//             }
//             fs << std::endl;
//         }
//     }// Write texture coordinatesfs << "\nPOINT_DATA " << nr_points << "\nTEXTURE_COORDINATES tcoords 2 float\n";for (unsigned int i = 0; i < nr_points; ++i) {//fs << texcoord[i][0] << " " << texcoord[i][1] << "\n";fs << texcoord[i][1] << " " << texcoord[i][0] << "\n";}fs << std::endl;// Close file
    fs.close ();return (0);}

Using PCL 1.8.0

// PCL 1.8.0
int save_vtk_file (const std::string &file_name, const pcl::PCLPointCloud2 &cloud, const std::vector<Eigen::Vector2f>& texcoord,unsigned precision)
{if (cloud.data.empty ()){PCL_ERROR ("[pcl::io::saveVTKFile] Input point cloud has no data!\n");return (-1);}// Open file
    std::ofstream fs;fs.precision (precision);fs.open (file_name.c_str ());unsigned int nr_points  = cloud.width * cloud.height;unsigned int point_size = static_cast<unsigned int> (cloud.data.size () / nr_points);// Write the header informationfs << "# vtk DataFile Version 3.0\nvtk output\nASCII\nDATASET POLYDATA\nPOINTS " << nr_points << " float" << '\n';// Iterate through the pointsfor (unsigned int i = 0; i < nr_points; ++i){int xyz = 0;for (size_t d = 0; d < cloud.fields.size (); ++d){int count = cloud.fields[d].count;if (count == 0)count = 1;          // we simply cannot tolerate 0 counts (coming from older converter code)int c = 0;if ((cloud.fields[d].datatype == pcl::PCLPointField::FLOAT32) && (cloud.fields[d].name == "x" || cloud.fields[d].name == "y" || cloud.fields[d].name == "z")){float value;memcpy (&value, &cloud.data[i * point_size + cloud.fields[d].offset + c * sizeof (float)], sizeof (float));fs << value;if (++xyz == 3)break;}fs << " ";}if (xyz != 3){PCL_ERROR ("[pcl::io::saveVTKFile] Input point cloud has no XYZ data!\n");return (-2);}fs << '\n';}// Write verticesfs << "\nVERTICES " << nr_points << " " << 2*nr_points << '\n';for (unsigned int i = 0; i < nr_points; ++i)fs << "1 " << i << '\n';//     // Write RGB values
//     int field_index = getFieldIndex (cloud, "rgb");
//     if (field_index != -1)
//     {
//         fs << "\nPOINT_DATA " << nr_points << "\nCOLOR_SCALARS scalars 3\n";
//         for (unsigned int i = 0; i < nr_points; ++i)
//         {
//             int count = cloud.fields[field_index].count;
//             if (count == 0)
//                 count = 1;          // we simply cannot tolerate 0 counts (coming from older converter code)
//             int c = 0;
//             if (cloud.fields[field_index].datatype == pcl::PCLPointField::FLOAT32)
//             {
//                 pcl::RGB color;
//                 memcpy (&color, &cloud.data[i * point_size + cloud.fields[field_index].offset + c * sizeof (float)], sizeof (RGB));
//                 int r = color.r;
//                 int g = color.g;
//                 int b = color.b;
//                 fs << static_cast<float> (r) / 255.0f << " " << static_cast<float> (g) / 255.0f << " " << static_cast<float> (b) / 255.0f;
//             }
//             fs << '\n';
//         }
//     }// Write texture coordinatesfs << "\nPOINT_DATA " << nr_points << "\nTEXTURE_COORDINATES tcoords 2 float\n";for (unsigned int i = 0; i < nr_points; ++i) {//fs << texcoord[i][0] << " " << texcoord[i][1] << "\n";fs << texcoord[i][1] << " " << texcoord[i][0] << "\n";}fs << '\n';// Close file
    fs.close ();return (0);
}

注意上面纹理的x和y的值,根据贴图的情况来看是否需要调换位置。

转载于:https://www.cnblogs.com/grandyang/p/6546701.html

PCL Save VTK File With Texture Coordinates 使用PCL库来保存带纹理坐标的VTK文件相关推荐

  1. PCL读取带rgb信息的asc文件C++

    PCL读取带rgb信息的asc文件 基本描述 代码与使用 基本描述 本代码适用于x y z r g b格式的asc文件,如果读者的asc文件是其他的格式,请修改相应的代码.其实整个代码的核心是将r g ...

  2. matlab保存数据用什么指令_MATLAB文件操作及保存文件save load fopen | 学步园

    一.保存文件 1.保存整个工作区 File->Save Workspace as...一个.mat文件 2.保存工作区的变量 在左工作区右击变量名,create M-File 3.save命令 ...

  3. R语言构建xgboost模型:模型的保存(xgb.save)和加载(xgb.load)、或者保存为R二进制文件(xgb.save.raw R binary vector)

    R语言构建xgboost模型:模型的保存(xgb.save)和加载(xgb.load).或者保存为R二进制文件(xgb.save.raw,R binary vector) 目录

  4. OpenGL Texture Coordinates纹理坐标的实例

    OpenGL simpletexcoords 先上图,再解答. 完整主要的源代码 源代码剖析 先上图,再解答. 完整主要的源代码 #include <vmath.h> #include & ...

  5. new file https 找不到路径_Python3用pathlib模块替代os.path进行文件路径的操作

    本文使用 Zhihu On VSCode 创作并发布 在 Python 3.4 之前和路径相关操作函数都放在 os 模块里面,尤其是os.path这个子模块,可以说os.path模块非常常用.而在 P ...

  6. PCL之Ubuntu16.04下编译libfreenect2和PCL以支持KinectV2点云处理

    转载于: https://shenxiaohai.me/2018/04/26/Ubuntu-freenect2-PCL/ 原因就是由于 OpenNI2.2 不支持 Kinect V2,导致我没法在 P ...

  7. pcl启动java代码_我的世界PCL启动器-Plain Craft Launcher(PCL启动器)下载 v1.0.9免费版--pc6下载站...

    PlainCraftLauncherPCL启动器是我的世界游戏的一款启动器,免费.开源,支持在线/离线两种模式,即使你没有网络,也可以畅玩,允许玩家方便快捷地安装.管理.运行游戏. Plain Cra ...

  8. python中file是什么意思中文_15_【Python学习分享文章】_file(文件)及其操作

    综述 - file(文件)的含义 Python 中的 file 不止使用 PC 时所说的单个文件,比如 .txt..exe 等这类文件,也包括"打开一个网址".程序间的通信数据等, ...

  9. android 录像工具,Android 屏幕录制(Surface\ Texture 录制)工具库

    你是否常常因为产品需要录制屏幕而不要状态栏而烦闷 ?? 你是不是常常因为产品需要录制直播视频而加班 ?? 你是不是常常因为要对一个surface同时录制两种Texture 分别存在的视频 (!!??? ...

  10. Unity3d 导入图片 自动修改Texture Type为Sprite (2D and UI) 及设置 Packing Tag为文件夹名

    版权声明:本文转自http://blog.csdn.net/huutu 转载请带上 http://www.liveslives.com/ http://blog.csdn.net/huutu/arti ...

最新文章

  1. 字节开启员工期权兑换,126美元每股;
  2. 欧拉函数/欧拉函数打表 lightoj1370(java/c++ )
  3. android模拟器启动没有拨号功能
  4. 程序员的职业素养-读书笔记
  5. C#基础之如何判断两个文件内容是否相同
  6. python为什么没有指针_Python 没有指针,如何解算法题?
  7. 操作系统Ubuntu(实验三四)
  8. Linux start-kernel
  9. python音乐推荐系统的设计与实现_基于协同过滤的音乐推荐系统
  10. 怎么用计算机知道密码,如何用电脑看到自家路由器的密码
  11. 解决方案:微信小程序下载文档出错downloadFile:fail url not in domain list
  12. 中企海外周报 | 华为在德国发布mate30系列手机;一汽新车亮相法兰克福车展
  13. Linux安装flux护眼软件
  14. 按月统计的sql语句
  15. HTML5设计更具有交互性的标签方法(含智能辅助设备使用的HTML5,翻译资料)
  16. java中between and什么意思,关于 oracle between and的用法!
  17. FME 安装破解及与ArGIS冲突的解决方法
  18. 新手做SEO迷茫时应该做什么
  19. Microsoft Project
  20. 循环神经网络-高级篇RNN Classifier

热门文章

  1. 微信小程序教程笔记5
  2. pytorch加载模型报错RuntimeError:Error(s) in loading state_dict for DataParallel
  3. Linux学习笔记(11)
  4. Caffe学习:Blobs, Layers, and Nets
  5. 基于深度学习的WLAN个体识别实践
  6. python中jieba分词快速入门
  7. 开源爬虫框架各有什么优缺点?
  8. java发送hotmail邮件,使用javamail将电子邮件发送到hotmail时遇到问题
  9. chrome 插件开发各种功能demo_Chrome扩展开发-编写一个浏览器插件
  10. latex 图片整行居中 /centering无效