PCL点云格式转换成tiff格式

2020-07-15  本文已影响0人  book_02

近期,需要把PCL的点云格式转换成tiff格式的图片,然后在halcon中处理。
总结转换过程如下

1. 转换函数(C++代码)

主要思路:

  1. 使用了libtiff库,来写tiff格式
  2. 把点云的x,y,z通道转换成tiff格式图片的三通道。
  3. 所以后续读取tiff格式图片转换成点云时,注意三通道代表x,y,z的顺序
  4. 写tiff格式的时候就是设置文件头,然后把数据一个字节一个字节的写进去

函数说明:

  1. pointcloud2tiff()是主要的转换函数,把PCL的点云数据cloud,写到filename文件中去
  2. main()写了调用示例,读取"test_tif.ply"点云文件,转换成tiff格式,写到"test.tif"文件中去
#include <iostream>
#include <pcl/io/ply_io.h>
#include <pcl/point_cloud.h>
#include <pcl/point_types.h> 
#include <string>
#include "tiffio.h"

using namespace std;

void pointcloud2tiff(const pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud, const std::string filename)
{
    TIFF *out = TIFFOpen(filename.c_str(), "w");
    int sampleperpixel = 3; // x, y, z
    int bitspersample = 32; //float
    int width = cloud->width;
    int height = cloud->height;
    float *image = new float[width*height*sampleperpixel];
    int linesamples = sampleperpixel * width;
    int linebytes = linesamples * sizeof(float);
    for (int r = 0; r < height; ++r) {
        for (int c = 0; c < width; ++c) {
            image[r*(linesamples)+3 * c + 0] = (*cloud)(c, r).x;
            image[r*(linesamples)+3 * c + 1] = (*cloud)(c, r).y;
            image[r*(linesamples)+3 * c + 2] = (*cloud)(c, r).z;
        }
    }
    // set header
    TIFFSetField(out, TIFFTAG_IMAGEWIDTH, width);                   // set the width of the image
    TIFFSetField(out, TIFFTAG_IMAGELENGTH, height);                 // set the height of the image
    TIFFSetField(out, TIFFTAG_SAMPLESPERPIXEL, sampleperpixel);     // set number of channels per pixel
    TIFFSetField(out, TIFFTAG_BITSPERSAMPLE, bitspersample);        // set the size of the channels
    TIFFSetField(out, TIFFTAG_ORIENTATION, ORIENTATION_TOPLEFT);    // set the origin of the image.
                                                                    // Some other essential fields to set that you do not have to understand for now.
    TIFFSetField(out, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
    TIFFSetField(out, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB);
    TIFFSetField(out, TIFFTAG_SAMPLEFORMAT, SAMPLEFORMAT_IEEEFP);

    unsigned char  *buf = NULL;
    if (TIFFScanlineSize(out)) {
        buf = (unsigned char *)_TIFFmalloc(linebytes);
    }
    else {
        buf = (unsigned char *)_TIFFmalloc(TIFFScanlineSize(out));
    }

    // We set the strip size of the file to be size of one row of pixels
    TIFFSetField(out, TIFFTAG_ROWSPERSTRIP, TIFFDefaultStripSize(out, width*sampleperpixel));

    //Now writing image to the file one strip at a time
    for (int row = 0; row < height; row++) {
        //memcpy(buf, &image[(height - row - 1)*linebytes], linebytes * sizeof(float));
        memcpy(buf, &image[row*linesamples], linebytes);
        if (TIFFWriteScanline(out, buf, row, 0) < 0) {
            fprintf(stderr, "scanline %d: Write error.\n", row);
            break;
        }
    }

    TIFFClose(out);
    if (buf) {
        _TIFFfree(buf);
    }
    if (image) {
        delete[]image;
    }
}

int main()
{
    pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZRGB>);

    pcl::io::loadPLYFile<pcl::PointXYZRGB>("test_tif.ply", *cloud);

    pointcloud2tiff(cloud, "test.tif");    

    return 0;
}

2. 其他说明

2.1 libtiff库

libtiff库的安装使用,可参考官网 http://www.libtiff.org/

按照说明,编译安装即可。

使用的时候建议用cmake来配置

2.2 扩展说明

  1. 上面的代码是把x,y,z通道保存到tif中去,如果需要把r,g,b等其他信息也保存进去,注意sampleperpixel和tiff文件头的设置
  2. 根据上面的代码,可以不限于PCL的点云格式,只要把相应的x,y,z信息填进去即可转换成tiff
上一篇下一篇

猜你喜欢

热点阅读