哼唧,最近做一个相机激光雷达标定的大作业,点云数据是ASCII格式的,网上找到了读取代码,但是有点bug,虽然被我de下去了,emmm,但是挺费事,de了快一上午,不敢想啊。
文件格式
依次是x,y,z,r,g,b,scale,intensity
读取代码
参考:PCL读取带rgb信息的asc文件C++_pcl支持asc文件吗_一行风的博客-CSDN博客
类定义:
#include <iostream>
#include <pcl/point_cloud.h> // for PointCloud
#include <pcl/point_types.h>
#include <fstream>
#include <string>
#include <sstream>
#include <vector>
#include <string>
template <class PointT>
class read_ascii_rgb {
private:
std::string file_name;
using PointCloudPtr = typename pcl::PointCloud<PointT>::Ptr;
PointCloudPtr cloud;
public:
read_ascii_rgb(const std::string file_path) {
file_name = file_path;
cloud = PointCloudPtr(new pcl::PointCloud<PointT>);
}
PointCloudPtr read() {
std::stringstream ss;
std::vector<PointT> v;
std::ifstream ifs(file_name);
std::string buffer;
if (!ifs) {
std::cout << "Open file fail at" << file_name << std::endl;
exit(1);
}
int i_output = 0;
while (std::getline(ifs, buffer)) {
PointT tmp;
ss.clear();
ss.str(buffer);
// ss << buffer;
unsigned r, g, b;
double scale, intensity;
ss >> tmp.x >> tmp.y >> tmp.z >> r >> g >> b >> scale >> intensity;
// tmp.intensity = intensity;
// if(i_output<=10){
// std::cout<<ss.str()<<std::endl;
// std::cout<<buffer<<std::endl;
// std::cout<<tmp.x<<" "<<tmp.y<<" "<<tmp.z<<" "<<r<<" "<<g<<" "<<b<<" "<<scale<<" "<<intensity<<" "<<std::endl;
// i_output++;
// }
int rgb = (r << 16 | g << 8 | b);
tmp.rgb = *reinterpret_cast<float*>(&rgb);
//std::cout << tmp.rgb << std::endl;
v.push_back(tmp);
}
cloud->height = 1;
cloud->width = v.size();
cloud->points.resize(cloud->width*cloud->height);
std::cout << cloud->width << std::endl;
for (auto i = 0; i < v.size(); i++) {
cloud->points[i].x = v[i].x;
cloud->points[i].y = v[i].y;
cloud->points[i].z = v[i].z;
cloud->points[i].rgb = v[i].rgb;
// cloud->points[i].r = 255;
// cloud->points[i].g = 255;
// cloud->points[i].b = 255;
// cloud->points[i].a = 255;
// cloud->points[i].intensity = v[i].intensity;
}
return cloud;
}
};
调用代码
#include<iostream>
#include "include/read_txt.hpp"
#include <pcl/visualization/cloud_viewer.h>
#include <pcl/visualization/pcl_visualizer.h>
#include <pcl/io/pcd_io.h> // 读写
using namespace std;
typedef pcl::PointXYZRGB PointT;
pcl::visualization::PCLVisualizer viewer("PointCloud");
int main(int argc, char const *argv[])
{
string path_folder = "/home/room401/ZhangShuo/MMS/data/Cam_Lidar_calibrate/lidar_txt";
string file_name = path_folder+"/10.txt";
read_ascii_rgb<PointT> a= read_ascii_rgb<PointT>(file_name);
pcl::PointCloud<PointT>::Ptr cloud= a.read();
// PointT tmp;
// tmp.intensity
cout<<"点云信息: "<<*cloud<<endl;
pcl::PCDWriter writer;
writer.write("cloud.pcd", *cloud, true);
viewer.removeAllPointClouds();
viewer.addPointCloud(cloud, "cloud");
viewer.spin();
// viewer.spinOnce(1000);
return 0;
}
遇到的坑
这里用stringstreanm逐行读取,先用getline函数从ifstream中读取一行存至std::string中,接着将string转到stringstreanm中,使用>>进行数值读取。
一个细节是从string转存到stringstreanm时候,应该先clear,这样才能保证之前的读取被清空,否则就会出现大量重复坐标点。。。