为什么point-cloud-library的loadPCDFile这么慢?

时间:2017-04-20 14:00:24

标签: c++ point-cloud-library

我从pcd文件中读取了220万个点,而loadPCDFile在Release和Debug模式下都使用了ca 13 sek。鉴于像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;
}

(使用PCL 1.8,Visual Studio 2015)

3 个答案:

答案 0 :(得分:1)

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

pcl::PointCloud<pcl::PointXYZ>::Ptr tempCloud(new pcl::PointCloud<pcl::PointXYZ>);

加载调用是相同的:

pcl::io::loadPCDFile(fp, *tempCloud);

但为了保存为二进制文件,请使用:

pcl::io::savePCDFileBinary(fp, *tempCloud);

以防万一它有所帮助,这里有一段我​​用来加载和保存云的代码(我稍微构建它们,但它可能基于一个例子,所以idk有多重要但是你可能想要如果你切换到二进制并且仍然看到很长的加载时间,请使用它。

//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;
            }
        }
  • 列表项

答案 1 :(得分:1)

以下摘要......

-PCL在加载云比较格式化的pcd文件时略慢。看看标题,CC似乎为pcl不喜欢的每个点“_”添加了一个额外的变量,并且必须格式化。但这只是30%-40%加载时间的差异。

- 基于以下结果:使用相同大小的点云(3m),我的计算机花了13秒钟从云比较加载它,而程序是在调试模式下编译的,在发布模式下加载相同的云只需0.25秒,我认为你是在调试模式下运行。根据您编译/安装pcl的方式,您可能需要重建pcl以生成适当的发布库。我的猜测是,无论你认为从调试到发布的改变,你实际上并没有参与pcl发布库。

在几乎所有功能的PCL中,从调试到发布的过程通常会使处理速度提高一到两个数量级(由于pcl大量使用大型数组对象,必须在调试模式下以不同的方式进行管理才能实现可见性)< / p>

使用云比较文件测试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();

云比较生成彩色云(3米点颜色) cloud compare generated colored cloud (3m points with color)

在调试中运行,使用3米长的云重现您的近似加载时间 Running in debug reproduced your approximate load time with a 3m pt cloud

在发布中运行

Running in release

答案 2 :(得分:0)

pcl example比较时,这看起来是正确的。我认为loadPCDFile的主要工作是在函数pcl::PCDReader::read中完成的,该函数位于文件pcd_io.cpp中。在检查二进制数据的代码时,就像在您的情况下一样,有3 nested for loops检查每个字段的数字数据是否有效。确切的代码注释是

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

这可能很费时间。但是,我猜测。