因实验需要,需要对PLY文件进行读取,因为所使用的PLY文件是利用深度相机获得,所以文件格式与一般的标准的PLY文件稍微有些出入。采用了网上读取的各种方法结果都会有些问题。所以对整个过程进行了总结,来记录一下。
通过数据文件可以发现,本文件中一行是XYZ一行是RGB。
利用PCL中的函数pcl::io::loadPLYFile()进行文件读取时,会报错:
[pcl::PLYReader] F:\PLY\fakepeople7.ply:12: property ‘list uint8 int32 vertex_indices’ of element ‘face’ is not handled [pcl::PLYReader]
F:\PLY\fakepeople7.ply:14: parse error [pcl::PLYReader]
F:\PLY\fakepeople7.ply:14: parse error: element property count doesn’t match the declaration in the header
[pcl::PLYReader::read] problem
parsing header! [pcl::PLYReader::read] problem parsing header!
尝试修改文件的头部声明,还是无法解决。
参考链接:https://blog.csdn.net/Charles_ke/article/details/86597223
运行时在函数pcl::io::loadPolygonFilePLY()会报错。
但是同样的代码,换一个PLY文件进行可视化,就有结果:
该PLY文件的数据格式如下:
考虑到可能是数据格式的问题,所以最后采用最笨的办法,对PLY文件按行读取,来生成最后的PCD文件。
大概思路:按行读取文件,第3行确定点的个数;然后按行继续读取文件中点云的坐标与颜色信息,并生成最终的点云。
struct point3f {
float x;
float y;
float z;
};
struct rgb3d {
int r;
int g;
int b;
};
PointCloud::Ptr read_ply(char* filename) { //输入为文件路径
pcl::PointCloud<pcl::PointXYZRGB>::Ptr cloud(new pcl::PointCloud<pcl::PointXYZRGB>);
ifstream file;
file.open(filename);
string temp;
int i = -1;
vector<point3f> xyz;
vector<rgb3d> rgb;
int num;
while (getline(file, temp)) //按行读取并赋值给temp
{
i++;
point3f p;
rgb3d c;
stringstream ss;
if (i == 3) {
num = atoi(temp.substr(15).c_str()); //在本文件中第三行存取了点的个数
}
else {
if (i > 12 && i< num * 2 + 13) {
if (i % 2 != 0) {
ss << temp;
ss >> p.x; ss >> p.y; ss >> p.z;
xyz.push_back(p); //点的坐标存储
}
else {
ss << temp;
ss >> c.r; ss >> c.g; ss >> c.b;
rgb.push_back(c); //点的颜色存储
}
}
else {
continue;
}
}
}
cloud->width = num;
cloud->height = 1;
cloud->is_dense = false;
cloud->points.resize(cloud->width * cloud->height);
for (int j = 0; j < xyz.size(); j++) {
cloud->points[j].x = xyz[j].x;
cloud->points[j].y = xyz[j].y;
cloud->points[j].z = xyz[j].z;
cloud->points[j].r = rgb[j].r;
cloud->points[j].g = rgb[j].g;
cloud->points[j].b = rgb[j].b;
}
return cloud;
}
最后文件的可视化效果如下: