欢迎点云相关产学研的学者和团体加入我们。
首先,在PCL(Point Cloud Learning)中国协助发行的书[1]提供光盘的第16章例2文件夹中,打开名为build_tree.cpp的代码文件,在同文件夹下有data文件夹包含测试数据。
下面开始解释上面打开的源代码中的关键语句,从main()函数开始,我们从加载一组模型特征数据开始,loadFeatureModels方法循环遍历从命令行获取的路径,从而加载路径下所有的pcd文件。在loadFeatureModels内部,调用loadHist,该函数,打开遍历路径得到的每个pcd文件,并读取其文件头,检查是否包含VFH标志位,如果有VFH标志为,则同时存储打开的数据和文件到vfh_model模型特征数据存储变量,该变量用一个字符串存储文件名,用一个向量存储文件对应的VFH特征向量。
当所有的模型VFH特征文件加载完成后,我们将它们转换为FLANN的格式,
// 转化数据为FLANN格式
flann::Matrix<float> data (new float[models.size () * models[0].second.size ()], models.size (), models[0].second.size ());
for (size_t i=0; i<data.rows; ++i)
for (size_t j =0; j <data.cols; ++j)
data[i][j] = models[i].second[j];
为了在测试阶段方便,不需要重新加载所有的模型特征数据,我们存储转化后的数据到磁盘,方便在测试时使用。
// 保存数据到磁盘
flann::save_to_file (data, training_data_h5_file_name, "training_data");
std::ofstream fs;
fs.open (training_data_list_file_name.c_str ());
for (size_t i=0; i<models.size (); ++i)
fs<< models[i].first <<"\n";
fs.close ();
最后,我们利用转化的数据创建kdtree,并将其结构保存到磁盘中,以备后面使用。
pcl::console::print_error ("Building the kdtree index (%s) for %d elements...\n", kdtree_idx_file_name.c_str (), (int)data.rows);
flann::Index<flann::ChiSquareDistance<float> > index (data, flann::LinearIndexParams ());
//flann::Index<flann::ChiSquareDistance<float>> index (data, flann::KDTreeIndexParams (4));
index.buildIndex ();
index.save (kdtree_idx_file_name);
在这里我们利用LinearIndex,使用Chi平方距离度量进行朴素模式匹配搜索(brute-force search),可以通过注释掉第一行,取消注释第二行,来利用KDTreeIndex建立kdtree,其实,LinearIndex和FLANN中的KDTreeIndex两者最重要的区别是,利用KDTreeIndex进行搜索匹配时要快得多,同时产生近似的结果,而不是绝对的结果。
截止现在,就完成了训练阶段,总结为以下步骤:
1. 遍历给定的目录,查看所有pcd文件,测试它们是否有VFH标志位,并加载到内存中。
2. 转化数据为FLANN格式并存储到磁盘。
3. 利用FLANN数据建立kdtree结构,并将其保存到磁盘。
未完待续,敬请关注“基于VFH描述子的聚类识别与6自由度位姿估计(3)”的其他内容。