C++ 为什么点云库是';加载PCD文件这么慢?
我正在从一个PCD文件中读取220万个点,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
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();