转换点云文件格式类型——将obj或者自定义类型文件转换成pcd,自定义类型文件可以设置前 n 行为无效数据行

本文是在对点云处理时,为了方便对选定文件夹下特定格式文件转换成pcd类型,所写的小工具。
特点是:
1.能获得指定文件夹下的指定类型的文件,并对文件进行类型转换
2.目前支持转换成pcd文件,源文件格式可以为 obj 和自定义的文件类型(假设前 n 行 为无效数据行,控制台下可以以参数 -iv n 形式指定)
3.可以将自定义文件类型数据读入到内存里,返回点云智能指针。
4.只支持 ascii 文本格式

需要说明的是:以下代码依赖 PCL 点云库 和 boost 库,boost库同时也是 pcl 库的依赖库,所以只需要配置 pcl 库。

raw2pclType.h 文件

#pragma once
#include <vector>
#include <string>
#include <fstream>
#include <pcl/io/pcd_io.h>
#include <pcl/io/obj_io.h>
#include <iostream>
#include <memory>
#include <iomanip>
#include <pcl/console/parse.h>
#include <pcl/io/obj_io.h>
#include <pcl/io/pcd_io.h>
#include <boost/filesystem.hpp>
#include <boost/xpressive/xpressive_dynamic.hpp>

namespace fg 
{
    enum PcDataType
    {
        INVALID_TYPE, PCD, OBJ, MEMORY, RAW
    };
    void parseCommandLine(int argc, char *argv[], PcDataType &srcTp, PcDataType &dsTp, std::string &ipth, int &invalidRows, std::string &opth, bool &isRecursive);
    void getDirectoryTreeFormat(const boost::filesystem::path &src, std::vector<std::string> &directoryTree, const std::string &form, const bool isRecursive);
    std::string enum2string(const PcDataType pct);

    class PointCloudDataFormatTrans
    {
    public:
        PointCloudDataFormatTrans(const std::string &ifile, const int inValidRows, const std::string &outDir, const PcDataType srcTp, const PcDataType dsTp);
        ~PointCloudDataFormatTrans() {}
        pcl::PointCloud<pcl::PointXYZ>::Ptr run();

    private:
        std::string m_ifile;
        std::string m_outDir;
        PcDataType m_srcTp;
        PcDataType m_dsTp;
        int m_inValidRows;
    };
}

raw2pclType.cpp 文件

#include "raw2pclType.h"

namespace fg
{
    void showHelp(char *filename)
    {
    std::cout << std::endl;
    std::cout << "***************************************************************************" << std::endl;
    std::cout << "*                                                                         *" << std::endl;
    std::cout << "*             Correspondence Grouping Tutorial - Usage Guide              *" << std::endl;
    std::cout << "*                                                                         *" << std::endl;
    std::cout << "***************************************************************************" << std::endl << std::endl;
    std::cout << "Usage: " << filename << " filePathName -f format[ obj or pcd ]" << std::endl << std::endl;
    std::cout << "Options:" << std::endl;
    std::cout << "     -h(optional):     Show this help." << std::endl;
    std::cout << "     -r(optional):     Recursively find the src-type files that will be converted,otherwise inside current folder default." << std::endl;
    std::cout << "     -st:              the src-type of files that will be converted,supporting obj and any pure three-demension-data file." << std::endl;
    std::cout << "     -dt:              the dst-type of files that will be converted,only supporting pcd format." << std::endl;
    std::cout << "     -i:               the direct including all files that need to be converted." << std::endl;
    std::cout << "     -iv(optional):    the number of beginning-rows of invalid data for src file,default 0." << std::endl;
    std::cout << "     -o(optional):     the direct that all tranformed files to be outputted to." << std::endl;
    std::cout << "     for example: raw2pclType_v2.exe -r -st[raw,obj] -dt[pcd] -i d:/ddf/in -o d:/out -iv 6" << std::endl;
    }

    void parseCommandLine(int argc, char *argv[], PcDataType &srcTp, PcDataType &dsTp, std::string &ipth, int &invalidRows, std::string &opth,bool &isRecursive)
    {
        //Show help
        if (pcl::console::find_switch(argc, argv, "-h"))
        {
            showHelp(argv[0]);
            exit(0);
        }

        if (argc<3)
        {
            std::cout << "number of parameters is incorrect ! \n";
            showHelp(argv[0]);
            exit(-1);
        }

        std::string opt;
        if (pcl::console::parse_argument(argc, argv, "-o", opt) != -1)
            opth = opt;
        else
            opth = std::string();

        std::string iv;
        if (pcl::console::parse_argument(argc, argv, "-iv", iv) != -1)
            invalidRows = std::stoi(iv);
        else
            invalidRows = 0;

        if (pcl::console::find_switch(argc, argv, "-r"))
            isRecursive = true;
        else
            isRecursive = false;

        std::string ipt;
        if (pcl::console::parse_argument(argc, argv, "-i", ipt) != -1)
            ipth = ipt;
        else
        {
            std::cout << "No files path! \n";
            showHelp(argv[0]);
            exit(-1);
        }

        std::string srcType, dsType;
        if (pcl::console::parse_argument(argc, argv, "-st", srcType) != -1)
        {
            if (srcType=="memory")
            {
                std::cout << "format is not supported! \n";
                showHelp(argv[0]);
                exit(-1);
            }
            else if (srcType.compare("pcd")==0)
            {
                srcTp = PcDataType::PCD;
            }
            else if (srcType.compare("obj") == 0)
            {
                srcTp = PcDataType::OBJ;
            }
            else if (srcType.compare("raw")==0)
            {
                srcTp = PcDataType::RAW;
            }
            else
            {
                std::cout << "format is not supported ! \n";
                showHelp(argv[0]);
                exit(-1);
            }
        }
        else
        {
            std::cout << "target format is missing! \n";
            showHelp(argv[0]);
            exit(-1);
        }

        if (pcl::console::parse_argument(argc, argv, "-dt", dsType) != -1)
        {
            if (dsType == "memory")
            {
                std::cout << "format is not supported! \n";
                showHelp(argv[0]);
                exit(-1);
            }
            else if (dsType.compare("pcd") == 0)
            {
                dsTp = PcDataType::PCD;
            }
            /*else if (dsType.compare("obj") == 0)
            {
                dsTp = PcDataType::OBJ;
            }*/
            else
            {
                std::cout << "format is not supported ! \n";
                showHelp(argv[0]);
                exit(-1);
            }
        }
        else
        {
            std::cout << "target format is missing! \n";
            showHelp(argv[0]);
            exit(-1);
        }
    }

    bool notPCD(const boost::filesystem::path &src)
    {
        if (src.has_extension())
        {
            const boost::filesystem::path extFile = src.extension();
            std::string strExt = extFile.string();
            if (strExt.compare(".pcd") == 0)
                return false;
        }
        return true;
    }

    void getDirectoryTreeFormat(const boost::filesystem::path &src, std::vector<std::string> &directoryTree, const std::string &form, const bool isRecursive)
    {
        boost::xpressive::sregex reg = boost::xpressive::sregex::compile(std::string(".*") + form);

        boost::filesystem::directory_iterator end_itr; // 缺省构造生成一个结束迭代器
        for (boost::filesystem::directory_iterator it(src); it != end_itr; ++it)
        {
            if (boost::filesystem::is_directory(it->status()))
            {
                if (isRecursive)
                {
                    getDirectoryTreeFormat(it->path(), directoryTree, form, isRecursive);
                }   
            }
            else if (boost::filesystem::is_regular_file(it->status()) && (boost::xpressive::regex_match(it->path().string(), reg))&& notPCD(it->path()))
            {
                directoryTree.push_back(it->path().string());
            }
        }
    }

    std::string enum2string(const PcDataType pct)
    {
        using string = std::string;
        switch (pct)
        {
        case PcDataType::PCD:
            return string("pcd");
        case PcDataType::OBJ:
            return string("obj");
        case  PcDataType::MEMORY:
            return string("memory");
        case  PcDataType::RAW:
            return string();
        default:
            return string();
        }
    }

    PointCloudDataFormatTrans::PointCloudDataFormatTrans(const std::string &ifile, const int inValidRows, const std::string &outDir, const PcDataType srcTp, const PcDataType dsTp):
        m_srcTp(srcTp), m_dsTp(dsTp), m_outDir(outDir),m_ifile(ifile), m_inValidRows(inValidRows)
    {}

    pcl::PointCloud<pcl::PointXYZ>::Ptr fg::PointCloudDataFormatTrans::run()
    {
        using BoostPath = boost::filesystem::path;

        //路径构造
        BoostPath ptLocal(m_ifile);
        BoostPath title;
        BoostPath dir = ptLocal.branch_path();
        BoostPath extName;
        if (ptLocal.has_extension())
        {
            title = ptLocal.stem();
            extName = ptLocal.extension();
        }
        else
            title = ptLocal.leaf();

        std::string ofPathName;
        if (m_outDir.empty())
        {
            ofPathName = dir.string() + std::string("\\") + title.string() + std::string(".") + enum2string(m_dsTp);
        }
        else
        {
            ofPathName = m_outDir + std::string("\\") + title.string() + std::string(".") + enum2string(m_dsTp);
        }

        //数据读取
        pcl::PointCloud<pcl::PointXYZ>::Ptr m_cloudData(new pcl::PointCloud<pcl::PointXYZ>);
        m_cloudData->clear();
        m_cloudData->reserve(100000);

        switch (m_srcTp)
        {
        case fg::OBJ:
        {
            pcl::OBJReader reader;
            reader.read(m_ifile, *m_cloudData);
            break;
        }
        case fg::RAW:
        {
            std::ifstream infile;
            infile.open(m_ifile);
            assert(infile.is_open());

            std::string s;
            float fDataX, fDataY, fDataZ;

            for (size_t i = 0; i < m_inValidRows; i++)
                getline(infile, s);

            while (getline(infile, s))
            {
                replace(s.begin(), s.end(), ',', ' ');
                std::stringstream ss(s);
                ss >> fDataX;
                ss >> fDataY;
                ss >> fDataZ;

                pcl::PointXYZ pointTmp(fDataX, fDataY, fDataZ);
                m_cloudData->push_back(pointTmp);
            }
            infile.close();
            break;
        }
        default:
        {
            std::cout << "the postfix of the inputfile is not supported !" << std::endl;
            exit(-1); 
        }
        }   

        if (m_dsTp == MEMORY)
            return m_cloudData;

        std::string postfix;
        switch (m_dsTp)
        {
        case PCD:
        {
            pcl::PCDWriter writer;
            writer.write(ofPathName, *m_cloudData);
            break;
        }

        /*case OBJ:
        {
        pcl::OBJWriter writer;
        writer.write(ofPathName, *m_cloudData);
        break;
        }*/

        default:
        {
            std::cout << "the postfix of the inputfile is not supported !" << std::endl;
            exit(-1);
        }
        }
        return m_cloudData;
    }
}

主文件 main.cpp

#include "raw2pclType.h"

int main(int argc, char *argv[])
{
    using string = std::string;
    using PcDataType = fg::PcDataType;
    PcDataType srcTp = PcDataType::INVALID_TYPE, dsTp = PcDataType::INVALID_TYPE;
    string ipth, opth;
    bool isRecursive = false;
    int inValidRows = 0;
    fg::parseCommandLine(argc, argv, srcTp, dsTp, ipth, inValidRows, opth, isRecursive);

    std::vector<std::string> filesPath;
    using BoostPath = boost::filesystem::path;
    BoostPath ipt(ipth);
    fg::getDirectoryTreeFormat(ipt, filesPath, fg::enum2string(srcTp), isRecursive);

    for (auto it = filesPath.cbegin(); it != filesPath.cend(); it++)
    {
        fg::PointCloudDataFormatTrans pointCloudDataFormatTrans(*it, inValidRows, opth, srcTp, dsTp);
        pcl::PointCloud<pcl::PointXYZ>::Ptr pc = pointCloudDataFormatTrans.run();
    }
}

在vs下编译成功后,运行可执行文件后,效果如下,使用方法如下图说明及示例:
这里写图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值