为什么点云库的 loadPCDFile 这么慢?
Why is the point-cloud-library's loadPCDFile so slow?
我正在从一个 PCD 文件中读取 220 万个点,并且 loadPCDFile
在 Release
和 Debug
模式下都使用了大约 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();
运行 在 Debug
中,用 3M 点云重现了您的大概加载时间:
运行 在 Release
:
我正在从一个 PCD 文件中读取 220 万个点,并且 loadPCDFile
在 Release
和 Debug
模式下都使用了大约 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();
运行 在 Debug
中,用 3M 点云重现了您的大概加载时间:
运行 在 Release
: