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

news/2024/11/9 22:15:05 标签: 数据结构与算法

我之前有一篇博客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.0
int 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 information
    fs << "# vtk DataFile Version 3.0\nvtk output\nASCII\nDATASET POLYDATA\nPOINTS " << nr_points << " float" << std::endl;

    // Iterate through the points
    for (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 vertices
    fs << "\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 coordinates
    fs << "\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 information
    fs << "# vtk DataFile Version 3.0\nvtk output\nASCII\nDATASET POLYDATA\nPOINTS " << nr_points << " float" << '\n';

    // Iterate through the points
    for (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 vertices
    fs << "\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 coordinates
    fs << "\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的值,根据贴图的情况来看是否需要调换位置。

本文转自博客园Grandyang,原文链接:PCL Save VTK File With Texture Coordinates 使用PCL库来保存带纹理坐标的VTK文件

,如需转载请自行联系原博主。


http://www.niftyadmin.cn/n/1496377.html

相关文章

用计算机求导,求导公式?

、公式法例如∫x^ndxx^(n1)/(n1)C∫dx/xlnxC∫cosxdxsinx等不定积分公式都应牢记&#xff0c;对于基本函数可直接求出原函数。2、换元法对于∫f[g(x)]dx可令tg(x),得到xw(t),计算∫f[g(x)]dx等价于计算∫f(t)w(t)dt。例如计算∫e^(-2x)dx时令t-2x,则x-1/2t,dx-1/2dt,代入后得&a…

jQuery通过Ajax向PHP服务端发送请求并返回JSON数据

服务端PHP读取MYSQL数据&#xff0c;并转换成JSON数据&#xff0c;传递给前端Javascript&#xff0c;并操作JSON数据。本文将通过实例演示了jQuery通过Ajax向PHP服务端发送请求并返回JSON数据。阅读本文的读者应该具备jQuery、Ajax、PHP相关知识&#xff0c;并能熟练运用。 JSO…

国防科大天河计算机应用,国防科大天河二号位居世界超级计算机TOP500榜首

据新华社广州 6月29日电(记者 陈冀)国家超级计算广州中心应用推广大会6月29日在广州召开&#xff0c;科学技术部副部长曹健林向广州超级计算中心授予了“国家超级计算广州中心”和“中国(广州)计算科学服务中心”牌匾&#xff0c;这标志着广州跻身国家级超级计算中心行列。目前…

定制你自己的敏捷方法:选择适合用于你的敏捷方法

\本文要点\\你的团队是独一无二的。你的敏捷方法应反映团队所处的环境。\\t在团队层&#xff0c;通常会以时间箱或计划、演示和反思的节奏来开展工作。\\t为治理流程&#xff0c;研究你的WIP&#xff08;在办任务&#xff09;以搞明白你自己的WIP限制。\\t有些团队发现更频繁的…

计算机图形期末试题,计算机图形学 2010 期末考试试题

计算机图形学 2010 期末考试试题计算机图形学试题一、写出下列述语的全称及中文含义。1、GKS (Graphics Kernel System)&#xff1a;图形核心系统2、PHIGS(Programmers Hierarchical Interactive Graphics System):程序员级分层结构交互图形系统(Programmers Hierarchical Inte…

计算机二级宝典考试题库,计算机二级宝典

计算机二级宝典是一款关于计算机考试备考的软件平台&#xff0c;不需要在电脑上练题&#xff0c;手机也能做题&#xff0c;这款软件上有着非常齐全的往年的例题&#xff0c;都有着非常俱全的解析&#xff0c;无论你身在何地&#xff0c;只要打开这款软件就可以开始做题练习&…

解决python3 UnicodeEncodeError: 'gbk' codec can't encode character '\xXX' in position XX

从网上抓了一些字节流&#xff0c;想打印出来结果发生了一下错误&#xff1a; UnicodeEncodeError: gbk codec cant encode character \xbb in position 8530: illegal multibyte sequence 代码 import urllib.request resurllib.request.urlopen(http://www.baidu.com) htmlBy…

南京技师学院计算机系,江苏南京技师学院2021年招生录取分数线

学生的等级观念还不是很强&#xff0c;所以还是要好好去培养自己的学习观念。从基本知识成长起来的学生有着较强的竞争力&#xff0c;学习没有任何的捷径&#xff0c;所以学习越早越好&#xff0c;年轻的是学习的精力也是更强的&#xff0c;记忆力也比较好&#xff0c;知识学习…