C++ 为什么点云库是';加载PCD文件这么慢?

C++ 为什么点云库是';加载PCD文件这么慢?,c++,point-cloud-library,C++,Point Cloud Library,我正在从一个PCD文件中读取220万个点,loadPCDFile在Release和Debug模式下使用ca 13秒。考虑到像CloudCompare这样的可视化程序可以在几毫秒的时间内读取文件,我希望我正在做一些比需要更难的事情 我做错了什么 我的PCD文件的顶部: # .PCD v0.7 - Point Cloud Data file format VERSION 0.7 FIELDS rgb x y z _ SIZE 4 4 4 4 1 TYPE F F F F U COUNT 1 1 1

我正在从一个PCD文件中读取220万个点,
loadPCDFile
Release
Debug
模式下使用ca 13秒。考虑到像CloudCompare这样的可视化程序可以在几毫秒的时间内读取文件,我希望我正在做一些比需要更难的事情

我做错了什么

我的PCD文件的顶部:

# .PCD v0.7 - Point Cloud Data file format
VERSION 0.7
FIELDS rgb x y z _
SIZE 4 4 4 4 1
TYPE F F F F U
COUNT 1 1 1 1 4
WIDTH 2206753
HEIGHT 1
VIEWPOINT 0 0 0 1 0 0 0
POINTS 2206753
DATA binary
    ¥•ÃöèÝÃájfD        ®§”ÃÍÌÝÃá:fD        H”ø¾ÝÃH!fD   .....
从我的代码中,读取文件:

#include <iostream>
#include <vector>

#include <pcl/common/common.h>
#include <pcl/common/common_headers.h>
#include <pcl/common/angles.h>
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
#include <pcl/visualization/pcl_visualizer.h>
#include <pcl/console/parse.h>
#include <pcl/filters/extract_indices.h>
#include <pcl/features/normal_3d.h>
#include <boost/thread/thread.hpp>

int main() {
    (...)

    pcl::PointCloud<pcl::PointXYZRGB>::Ptr largeCloud(new pcl::PointCloud<pcl::PointXYZRGB>);
    largeCloud->points.resize(3000000); //Tried to force resizing only once. Did not help much.

    if (pcl::io::loadPCDFile<pcl::PointXYZRGB>("MY_POINTS.pcd", *largeCloud) == -1) {
        PCL_ERROR("Couldn't read file MY_POINTS.pcd\n");
        return(-1);
    }

    (...)
    return 0;
}
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
int main(){
(...)
pcl::PointCloud::Ptr largeCloud(新pcl::PointCloud);
largeCloud->points.resize(3000000);//只尝试了一次强制调整大小。没有多大帮助。
if(pcl::io::loadPCDFile(“MY_POINTS.pcd”,*largeCloud)=-1){
PCL_错误(“无法读取文件MY_POINTS.pcd\n”);
返回(-1);
}
(...)
返回0;
}

(使用PCL 1.8和Visual Studio 2015)

与a相比,这看起来是正确的。我认为
loadPCDFile
的主要工作是在文件中的函数
pcl::PCDReader::read
中完成的。当检查代码中的二进制数据时,就像在您的例子中一样,会检查每个字段的数字数据是否有效。确切的代码注释是

// Once copied, we need to go over each field and check if it has NaN/Inf values and assign cloud

这可能很耗时。然而,我在猜测

我遇到的正是这种情况。 它可以简单地归结为文件存储方式。您的文件(加载所需的时间)几乎肯定是ASCII样式的点云文件。如果希望能够更快地加载(x100),请将其转换为二进制格式。作为参考,我在大约四分之一秒内加载了一个1M pt的云(但这取决于系统)

但为了保存为二进制文件,请使用以下命令:

pcl::io::savePCDFileBinary(fp, *tempCloud);
为了以防万一,这里是我用来加载和保存云的一段代码(我对它们进行了一点构造,但它可能基于一个示例,所以我不知道这有多重要,但如果您切换到二进制并且仍然看到很长的加载时间,您可能希望使用它)

//保存pt云
std::string filePath=getUserInput(“在此处输入文件名”);
int fileType=stoi(getUserInput(“0:binary,1:ascii”);
if(filePath.size()==0)
printf(“文件保存失败!\n”);
其他的
{
pcl::点云tempCloud;
copyPointCloud(*currentWorkingCloud,tempCloud);
tempCloud.width=currentWorkingCloud->points.size();
tempCloud.height=1;
tempCloud.is_density=false;
filePath=“../PointCloudFiles/”+文件路径;
std::cout下面的总结

  • PCL在加载云比较格式的PCD文件时稍微慢一点。查看标题,CC似乎在PCL不喜欢且必须格式化的每个点“\u1”上添加了一个额外的变量。但这只是加载时间的30%-40%的差异

  • 基于相同大小点云(3M)的结果,我的计算机在
    调试
    模式下编译程序时,从云计算加载它需要13秒,而在
    发布
    模式下加载相同的云计算只需要0.25秒。我认为您正在调试模式下运行。根据您编译/安装PCL的方式,您可能需要重建PCL以生成相应的
    发布
    构建。我的猜测是,无论您认为您正在做什么,从
    Debug
    更改为
    Release
    实际上并没有使用PCL Release库

在PCL中,在几乎所有功能中,从
Debug
移动到
Release
通常会使处理速度加快一到两个数量级(因为PCL大量使用大型数组对象,必须在
Debug
模式下以不同方式管理这些对象以实现可见性)



使用云比较文件测试PCL

以下是我运行以生成以下输出的代码:

std::cout << "Press enter to load cloud compare sample" << std::endl;
    std::cin.get();

    TimeStamp stopWatch = TimeStamp();
    pcl::PointCloud<pcl::PointXYZRGB>::Ptr tempCloud2(new pcl::PointCloud<pcl::PointXYZRGB>);
    pcl::io::loadPCDFile("C:/SO/testTorusColor.pcd", *tempCloud2);

    stopWatch.fullStamp(true);
    std::cout <<"Points loaded: "<< tempCloud2->points.size() << std::endl;
    std::cout << "Sample point: " << tempCloud2->points.at(0) << std::endl;
    std::cout << std::endl;

    std::cout << "Press enter to save cloud in pcl format " << std::endl;
    std::cin.get();
    pcl::io::savePCDFileBinary("C:/SO/testTorusColorPCLFormatted.pcd", *tempCloud2);

    std::cout << "Press enter to load formatted cloud" << std::endl;
    std::cin.get();

    stopWatch = TimeStamp();
    pcl::PointCloud<pcl::PointXYZRGB>::Ptr tempCloud3(new pcl::PointCloud<pcl::PointXYZRGB>);
    pcl::io::loadPCDFile("C:/SO/testTorusColorPCLFormatted.pcd", *tempCloud3);
    stopWatch.fullStamp(true);
    std::cout << "Points loaded: " << tempCloud3->points.size() << std::endl;
    std::cout << "Sample point: " << tempCloud3->points.at(0) << std::endl;
    std::cout << std::endl;

    std::cin.get();

std::cout我不知道是否重要,但我在加载云时从未调用过resize。我使用它是因为我想初始化足够大的云,这样加载函数就不必在读取inn数据时不断调整云的大小。但是这没有帮助。你确定时间是花在load语句中,而不是在可视化工具启动还是什么?pcd文件是由pcl创建的吗?您是否使用自定义点类型…?字段大小计数和类型与我在xyzrgb或xyzrgba文件类型中的任何内容都不匹配…我非常确定pcb文件中保存了二进制数据。(“data binary”位于pcb文件顶部。)可能没有解决OP的问题,但帮了我很多!+1
pcl::io::savePCDFileBinary(fp, *tempCloud);
//save pt cloud
        std::string filePath = getUserInput("Enter file name here");
        int fileType = stoi(getUserInput("0: binary, 1:ascii"));
        if (filePath.size() == 0)
            printf("failed file save!\n");
        else
        {
            pcl::PointCloud<pcl::PointXYZ> tempCloud;
            copyPointCloud(*currentWorkingCloud, tempCloud);
            tempCloud.width = currentWorkingCloud->points.size();
            tempCloud.height = 1;
            tempCloud.is_dense = false;

            filePath = "../PointCloudFiles/" + filePath;
            std::cout << "Cloud saved to:_" << filePath << std::endl;
            if (fileType == 0){pcl::io::savePCDFileBinary(filePath, tempCloud);}
            else
            {pcl::io::savePCDFileASCII(filePath, tempCloud);}
            
        }

//load pt cloud
        std::string filePath = getUserInput("Enter file name here");
        if (filePath.size() == 0)
            printf("failed user input!\n");
        else
        {
            filePath = "../PointCloudFiles/" + filePath;
            pcl::PointCloud<pcl::PointXYZ>::Ptr tempCloud(new pcl::PointCloud<pcl::PointXYZ>);

            if (pcl::io::loadPCDFile(filePath, *tempCloud) == -1) //* load the file
            {
                printf("failed file load!\n");
            }
            else
            {
                copyPointCloud(*tempCloud, *currentWorkingCloud); std::cout << "Cloud loaded from:_" << filePath << std::endl;
            }
        }
std::cout << "Press enter to load cloud compare sample" << std::endl;
    std::cin.get();

    TimeStamp stopWatch = TimeStamp();
    pcl::PointCloud<pcl::PointXYZRGB>::Ptr tempCloud2(new pcl::PointCloud<pcl::PointXYZRGB>);
    pcl::io::loadPCDFile("C:/SO/testTorusColor.pcd", *tempCloud2);

    stopWatch.fullStamp(true);
    std::cout <<"Points loaded: "<< tempCloud2->points.size() << std::endl;
    std::cout << "Sample point: " << tempCloud2->points.at(0) << std::endl;
    std::cout << std::endl;

    std::cout << "Press enter to save cloud in pcl format " << std::endl;
    std::cin.get();
    pcl::io::savePCDFileBinary("C:/SO/testTorusColorPCLFormatted.pcd", *tempCloud2);

    std::cout << "Press enter to load formatted cloud" << std::endl;
    std::cin.get();

    stopWatch = TimeStamp();
    pcl::PointCloud<pcl::PointXYZRGB>::Ptr tempCloud3(new pcl::PointCloud<pcl::PointXYZRGB>);
    pcl::io::loadPCDFile("C:/SO/testTorusColorPCLFormatted.pcd", *tempCloud3);
    stopWatch.fullStamp(true);
    std::cout << "Points loaded: " << tempCloud3->points.size() << std::endl;
    std::cout << "Sample point: " << tempCloud3->points.at(0) << std::endl;
    std::cout << std::endl;

    std::cin.get();