为什么点云库的 loadPCDFile 这么慢?

Why is the point-cloud-library's loadPCDFile so slow?

我正在从一个 PCD 文件中读取 220 万个点,并且 loadPCDFileReleaseDebug 模式下都使用了大约 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;
}

(使用 PCL 1.8 和 Visual Studio 2015)

与检查每个字段的数值数据是否有效的 pcl example. I think the main work of loadPCDFile is done in the function pcl::PCDReader::read, which is located in the file pcd_io.cpp. When checking the code for binary data, as it is in your case, there are 3 nested for loops 相比,这看起来是正确的。确切的代码注释是

// 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::PointCloud<pcl::PointXYZ>::Ptr tempCloud(new pcl::PointCloud<pcl::PointXYZ>);

加载调用相同:

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

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

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

以下摘要...

  • PCL 在加载云比较格式的 PCD 文件时稍慢。看headers,CC好像给PCL不喜欢的每个点“_”加了一个额外的变量,必须格式化掉。但这只是30%-40%加载时间的差异。

  • 基于相同大小的点云(3M),我的电脑用了13秒从云中加载它比较当程序在Debug模式下编译并且只在 Release 模式下加载相同的云需要 0.25 秒。我认为您 运行 处于调试模式。根据您 compiled/installed PCL 的方式,您可能需要重建 PCL 以生成适当的 Release 版本。我的猜测是,无论您认为从 Debug 更改为 Release 所做的任何事情,实际上都没有使用 PCL 发布库。

在 PCL 中,在几乎所有函数中,从 Debug 移动到 Release 通常会使处理速度提高一到两个数量级(由于 PCL大量使用大型数组 objects,必须在 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();

云比较生成的彩色云(3M点有颜色):

运行 在 Debug 中,用 3M 点云重现了您的大概加载时间:

运行 在 Release: