背景:
当你有一堆点云(pcd格式)以及对于的标记,你想放到PointNet里面训练。你需要把收集的点云(.pcd)存到一个h5文件里。
首先你需要把pcd们写成一个3x1024xN的数据集,3指的是(一个点的维度),1024指的是多少个点,N指的是多少个点云。
然后把标记写成一个1XN的数据集。
合成放到h5文件里。
详见下面代码。
注:项目结构
- src
- main.cpp
- my_io.cpp
- include
- my_io.h
- bin
- xxx.可执行文件
- raw
- xxx1.pcd
- xxx2.pcd
- ..... .pcd
- pcd_names_file.txt
- labels_file.txt
注:这里面的标记文件labels_file.txt,是需要你自己去为你的训练的点云类别去设置的。举个例子,你采了一个苹果的点云,那么你的苹果对应的id也就是标记可以设为0。
那么,
pcd_names_file.txt labels_file.txt
苹果1.pcd 0
香蕉1.pcd 1
苹果2.pcd 0
香蕉2.pcd 1
香蕉3.pcd 1
... ...
注:你使用matlab打开pointnet用的数据集(那些h5文件),你就会看见里面有个labels的数组,数字为0~39。
1. main的代码:
/*Author: AmbitiousRuralDog
Date: 2018/06/28
This a main file to call my_io functions to covert PCL's PCD-type
data to chunk-format HDF5 data
*/
#include
#include
#include
#include
#include "my_io.h"
using namespace std;
int main(int argc, char** argv){
MyIO my_io;
string h5_filename = "trainset1.h5";
my_io.combinePCDsAndLabelsIntoH5File(h5_filename, "raw_data/pcd_names_file1.txt", "raw_data/labels_file1.txt");
cout << "data is writed to " << h5_filename << endl;
return 0;
}
2. my_io.h的代码:
/*Author: AmbitiousRuralDog
Date: 2018/06/28
This a header file to declare my_io's functions that covert PCL's PCD-type
data to chunk-format HDF5 data
*/
#ifndef MYIO_H
#define MYIO_H
#include "H5Cpp.h"
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
typedef pcl::PointXYZI PT;
typedef pcl::PointCloud PCT;
class MyIO
{
public:
MyIO();
~MyIO();
int markDownStoredPCDNameAndItsLabel(const string &pcd_name, const int &label, const string &pcd_names_file, const string &labels_file);
int combinePCDsAndLabelsIntoH5File(const string &h5_file, const string &pcd_names_file, const string &labels_file);
int readFileAndCountHowManyClouds(const string &pcd_names_file);
private:
int readPCDs(const string &pcd_names_file, float *data, const unsigned int &pt_num);
int readLabels(const string &labels_file, int *data);
};
#endif // MYIO_H
3. my_io.cpp的代码
/*Author: AmbitiousRuralDog
Date: 2018/06/28
This a cpp file to define my_io's functions that covert PCL's PCD-type
data to chunk-format HDF5 data
*/
#include "my_io.h"
MyIO::MyIO()
{
}
MyIO::~MyIO(){
}
// This function is to store the label and corresponding pcd_file name into two seperate txt files.
// These txt files aim to be plugged in PointNet for training
int MyIO::markDownStoredPCDNameAndItsLabel(const string &pcd_name, const int &label, const string &pcd_names_file, const string &labels_file){
ofstream outfile, outfile2;
outfile.open(pcd_names_file, ofstream::app);
outfile2.open(labels_file, ofstream::app);
if (!outfile.is_open() | !outfile2.is_open())
return -1;
outfile << pcd_name + "\n";
outfile2 << to_string(label) + "\n";
outfile.close();
outfile2.close();
return 1;
}
// Extract a set of PCD files and combine them and write the result to a h5 file.
// Also write lables to a h5 file.
int MyIO::combinePCDsAndLabelsIntoH5File(const string &h5_file, const string &pcd_names_file, const string &labels_file){
unsigned int RANK_clouds = 3;
unsigned int RANK_labels = 2;
unsigned int pt_dim = 3;
unsigned int pt_num = 1024;
// From a file storing all PCD filenames, dynamically count how many PCD files are required to put into H5 file
unsigned int cloud_num;
cloud_num = readFileAndCountHowManyClouds(pcd_names_file);
if (cloud_num == -1) return 0;
const std::string DATASET_NAME("data");
const std::string LABELSET_NAME("label");
// Read clouds and labels and store as float array and int array respectively
float* data = new float [pt_dim*pt_num*cloud_num];
readPCDs(pcd_names_file, data, pt_num);
int* label = new int[cloud_num];
readLabels(labels_file, label);
// What is the size of each chunk of data
unsigned int cloud_chunksize = unsigned(floor(cloud_num/8));
if (cloud_chunksize < 1) cloud_chunksize = 1;
unsigned int pt_num_chunksize = unsigned(floor(pt_num/8));
if (pt_num_chunksize < 1) pt_num_chunksize = 1;
try
{
hid_t file_id;
// Open a h5 file for clouds
file_id = H5Fcreate(h5_file.c_str(), H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT);
hid_t space_id, dataset_id, chunk_dataset_id;
// Create a dataset
dataset_id = H5Pcreate(H5P_DATASET_CREATE);
// Create a dataspace for dataset
hsize_t dims[RANK_clouds] = {cloud_num, pt_num, pt_dim};
hsize_t dims_max[RANK_clouds] = {cloud_num, pt_num, pt_dim};
hsize_t chunk_dims[RANK_clouds] = {cloud_chunksize, pt_num_chunksize, 1};
H5Pset_chunk(dataset_id, RANK_clouds, chunk_dims);
space_id = H5Screate_simple(RANK_clouds, dims, dims_max);
// Change the dataset into a chunk-format dataset
chunk_dataset_id = H5Dcreate1(file_id,"data",H5T_NATIVE_FLOAT,space_id,dataset_id);
// Write data into chunk-format dataset
H5Dwrite(chunk_dataset_id, H5T_NATIVE_FLOAT, H5S_ALL, H5S_ALL, H5P_DEFAULT, data);
// Close dataspace dataset
H5Dclose(chunk_dataset_id);
H5Sclose(space_id);
H5Pclose(dataset_id);
hid_t space_id2, dataset_id2, chunk_dataset_id2;
// Create a dataset
dataset_id2 = H5Pcreate(H5P_DATASET_CREATE);
// Create a dataspace for dataset
hsize_t dims2[RANK_labels] = {cloud_num, 1};
hsize_t dims2_max[RANK_labels] = {cloud_num,1};
hsize_t chunk_dims2[RANK_labels] = {cloud_num, 1};
H5Pset_chunk(dataset_id2, RANK_labels, chunk_dims2);
space_id2 = H5Screate_simple(RANK_labels, dims2, dims2_max);
// Change the dataset into a chunk-format dataset
chunk_dataset_id2 = H5Dcreate1(file_id,"label",H5T_NATIVE_INT,space_id2,dataset_id2);
// Write data into chunk-format dataset
H5Dwrite(chunk_dataset_id2, H5T_NATIVE_INT, H5S_ALL, H5S_ALL, H5P_DEFAULT, label);
// Close dataspace dataset and h5 file
H5Dclose(chunk_dataset_id2);
H5Sclose(space_id2);
H5Pclose(dataset_id2);
H5Fclose(file_id);
}
// catch failure caused by the H5File operations
catch(H5::FileIException error)
{
error.printError();
return -1;
}
// catch failure caused by the DataSpace operations
catch(H5::DataSpaceIException error)
{
error.printError();
return -1;
}
// catch failure caused by the Group operations
catch(H5::GroupIException error)
{
error.printError();
return -1;
}
// catch failure caused by the DataSet operations
catch(H5::DataSetIException error)
{
error.printError();
return -1;
}
return 1;
}
// From a file storing all PCD filenames, dynamically count how many PCD files are required to put into H5 file
int MyIO::readFileAndCountHowManyClouds(const string &pcd_names_file){
ifstream in;
in.open(pcd_names_file);
if (!in.is_open())
return -1;
string textline;
unsigned int count = 0;
while (getline(in, textline)){
count++;
}
in.close();
return count;
}
// From a file storing all PCD filenames, combine all cloud data to a float array
int MyIO::readPCDs(const string &pcd_names_file, float *cloud_array, const unsigned int &pt_num){
ifstream in;
in.open(pcd_names_file);
if (!in.is_open())
return -1;
string textline;
unsigned int idx = 0;
while (getline(in, textline)){
PCT::Ptr a_cloud (new PCT);
pcl::io::loadPCDFile(textline,*a_cloud);
if (pt_num!=a_cloud->points.size())
{
cout << "Error: A cloud's point number is not equal " << pt_num << endl;
}
for (int j = 0; j < pt_num; j++){
cloud_array[idx] = a_cloud->points[j].x;
cloud_array[idx+1] = a_cloud->points[j].y;
cloud_array[idx+2] = a_cloud->points[j].z;
idx = idx+3;
}
}
return 1;
}
// From a file storing all PCD labels, combine all labels to a int array
int MyIO::readLabels(const string &labels_file, int *label_array){
ifstream in;
in.open(labels_file);
if (!in.is_open())
return -1;
unsigned int count = 0;
int a_label;
while (in >> a_label){
label_array[count] = a_label;
count++;
}
return 1;
}