利用stringstream缓存加速PCD文件读取
在用pcl读取点云文件的时候有时需要处理几十万点云数据,对于1-5万的点云直接用
pcl::io::loadPCDFile(“pointcloud.pcd”, cloud)
来读取确实很方便,但是大于点数大于20万时读取时间会额外加长,尤其debug模式下,所以自己写了一个读pcd格式的点云文件。如果用io流逐行读取,文件读取的时间会急剧增长,而一次性将数据会部读入内存之后再处理,达到减少IO次数的目的。
头文件:
#pragma once
#include "stdafx.h"
#include<iostream>
#include <fstream>
#include <regex>
#include <string>
#include <omp.h>
#include <pcl/io/pcd_io.h>
#include <Boost/smart_ptr/make_shared.hpp>
#include <pcl/point_cloud.h>
#include<pcl/visualization/cloud_viewer.h>
class parafile
{
public:
parafile();
~parafile();
pcl::PointCloud<pcl::PointXYZ> cloud;
const int MIN_ITERATOR_NUM=4;//最小并行要求
int tn;tn表示要设置的线程数量
void readtxt(std::string name);
///读取pcd文件
void setThreadNum(int ITERATOR_NUM);
//多线程方案
};
cpp文件:
#include "parafile.h"
parafile::parafile()
{
cloud.clear();
}
parafile::~parafile()
{
}
void parafile::readtxt(std::string name)
{
std::ifstream file1;
file1.open(name);
if (!file1)
{
std::cout << "Open file failed!" << std::endl;
exit(1);
}
while (!file1.eof())//检测前缀
//利用正则表达式匹配信息,这里只找了数据头和数据量,其余可以自己添加
{
std::regex reg1("[\u4E00-\u9FA5A-Za-z_]+"); //匹配大小字母数字和下划线
std::regex reg2("#+");
std::regex reg3("WIDTH");
std::string s1;
getline(file1, s1);
std::smatch r1;
if (regex_search(s1, r1, reg3))
{
std::stringstream strstr3;
int cloudwidth = 0; std::string part2;
strstr3.str(s1);
strstr3 >> part2;
strstr3 >> cloudwidth;
cloud.resize(cloudwidth);
}
if (!(regex_search(s1, r1, reg1) || regex_search(s1, r1, reg2)))
//跳出前缀信息检测,开始读取数据
{
pcl::PointXYZ point;
std::stringstream strstr2;
strstr2.str(s1);
float part;
strstr2>>part;
point.x = part;
strstr2 >> part;
point.y= part;
strstr2 >> part;
point.z = part;
cloud[0]=point;
break;
}
}
std::string buffer;//写入字符串流
buffer.assign(std::istreambuf_iterator<char>(file1), std::istreambuf_iterator<char>());
std::stringstream strstr;
strstr.str(buffer);
std::string linestr;
setThreadNum(cloud.size());
#pragma omp parallel for if( tn > 1) num_threads(tn)
//openmp并行计算
for (int i = 1; i < cloud.size(); i++)
{
pcl::PointXYZ point;
float part;
strstr >> part;
point.x = part;
strstr >> part;
point.y = part;
strstr >> part;
point.z = part;
cloud[i] = point;
}
file1.close();
}
void parafile::setThreadNum(int ITERATOR_NUM)
{
int ncore = omp_get_num_procs(); //获取执行核的数量
int max_tn = ITERATOR_NUM / MIN_ITERATOR_NUM;
tn = max_tn > 2 * ncore ? ncore : max_tn;
std::cout << "启用线程数量:" << tn << std::endl;
}
debugx64结果:
releasex64结果:
第一个时间是自己写的函数,第二个时间是pcl库函数,在debug模式下效率提升的还是很高的,release下也提高了快一倍