赞
踩
个人解析代码GitHub:https://github.com/ybgdgh/s3dis_semantic
S3DIS数据集是斯坦福大学开发的带有像素级语义标注的语义数据集,包含了rgb,depth,3d点云、mesh等。
官网:http://buildingparser.stanford.edu/dataset.html
官网github:https://github.com/alexsax/2D-3D-Semantics
还原点云数据有多种方式,可以通过直接解析自带的mat文件进行解析,也可以通过合成rgb和深度图进行解析。本文以Area_1数据为例。
数据集自带的mat文件包含了每一label的点云坐标、rgb,标注、物体体积、是否占有能属性组成。数据结构如下:
该mat文件包含一个struct结构体,结构体又往下分级。
可以用python直接解析该mat文件,本人对python不太熟悉,因此最后采用了将该mat文件转化为json脚本的形式,通过c++进行解析。
通过matlab解析json非常简单,只需要下载安装一个插件JSONlab,对应链接:https://github.com/fangq/jsonlab/#installation,
添加到matlab的toolkit文件加中,再将路径添加进行即可。matlab程序如下:
load('pointcloud.mat')
name_ALL = Area_1.Disjoint_Space;
for i=1:1:44
name=savejson('',name_ALL(i));
fid=fopen(['Adata_',num2str(i),'.json'],'w+');
fprintf(fid,'%s',name);
fclose(fid);
fprintf('%s \n',i);
end
本次只针对一个场景即Area_1进行解析,因此只采集了object所有对象下的结构体,该结构体下又包含多个子类,每一类都有对应的一套属性。
每个对象的内容如下:
{ "name": "conferenceRoom_1", "AlignmentAngle": -0, "color": [0.5,0.5,0], "object": [ { "name": "beam_1", "RGB_color": [ [71,64,54], [68,64,52], ... ... [-15.296,40.53,2.19] ] ] } ] }
object结构体下包含了其他如坐标、Voxels等信息。在这里将所有对象的数据分别存入不同文件(避免文件过大)
通过这种方式,将点云文件转化为json格式,再通过c++读取即可。程序如下:
json解析函数根据官方提供的代码进行了修改,官方代码只是用来解析pose.josn数据的,这里用boost::property_tree::ptree
来解析json格式。
#ifndef SEMANTIC2D3D_UTILS_H #define SEMANTIC2D3D_UTILS_H #include <iostream> #include <boost/property_tree/ptree.hpp> #include <boost/property_tree/json_parser.hpp> #include <pcl/common/eigen.h> #include <iostream> #include <boost/foreach.hpp> #include <vector> namespace Utils { /** Gets the RGB_color from a pose file ptree and returns it**/ inline bool getRGBcolor(const boost::property_tree::ptree &pt, std::vector<Eigen::Vector3d> &RGB) { // Read in RGB_color Eigen::Vector3d rgb_point; int i = 0; boost::property_tree::ptree object = pt.get_child("object"); BOOST_FOREACH (boost::property_tree::ptree::value_type &vtt, object) { boost::property_tree::ptree pt_tree = vtt.second; boost::property_tree::ptree RGB_color = pt_tree.get_child("RGB_color"); BOOST_FOREACH (boost::property_tree::ptree::value_type &v, RGB_color) { boost::property_tree::ptree tree = v.second; BOOST_FOREACH (boost::property_tree::ptree::value_type &vt, tree) { rgb_point[i] = vt.second.get_value<float>(); i++; } i = 0; // std::cout << rgb_point.transpose() << std::endl; RGB.push_back(rgb_point); } } return true; } inline bool getXYZpoints(const boost::property_tree::ptree &pt, std::vector<Eigen::Vector3d> &XYZ) { // Read in XYZ_color Eigen::Vector3d xyz_point; int i = 0; boost::property_tree::ptree object = pt.get_child("object"); BOOST_FOREACH (boost::property_tree::ptree::value_type &vtt, object) { boost::property_tree::ptree pt_tree = vtt.second; boost::property_tree::ptree point = pt_tree.get_child("points"); BOOST_FOREACH (boost::property_tree::ptree::value_type &v, point) { boost::property_tree::ptree tree = v.second; BOOST_FOREACH (boost::property_tree::ptree::value_type &vt, tree) { xyz_point[i] = vt.second.get_value<float>(); i++; } i = 0; // std::cout << rgb_point.transpose() << std::endl; XYZ.push_back(xyz_point); } } return true; } /** Load in the json pose files into a boost::ptree **/ inline boost::property_tree::ptree loadPoseFile(const std::string &json_filename) { // Read in view_dict boost::property_tree::ptree pt; std::ifstream in(json_filename); std::stringstream buffer; buffer << in.rdbuf(); read_json(buffer, pt); return pt; } /** Debugging function to print out a boost::ptree **/ void print(boost::property_tree::ptree const &pt) { using boost::property_tree::ptree; ptree::const_iterator end = pt.end(); for (ptree::const_iterator it = pt.begin(); it != end; ++it) { std::cout << it->first << ": " << it->second.get_value<std::string>() << std::endl; print(it->second); } } } // namespace Utils #endif // #ifndef SEMANTIC2D3D_UTILS_H
以上给出了解析json中点云坐标和rgb的程序。可根据文件树添加其他数据的解析程序,json的解析方式是一样的,只需要调整一下解析程序中的层数和对应的name即可。
主函数如下,主要是通过调用点云数据和rgb数据进行整体点云的拼接。由于点云数量过大,因此最后还是按文件分别保存了pcd文件。
#include <opencv2/opencv.hpp> #include "opencv2/imgcodecs.hpp" #include "opencv2/highgui/highgui.hpp" #include <vector> #include <string> #include <Eigen/Core> #include <unistd.h> #include <fstream> #include <cstring> #include <pcl/io/pcd_io.h> #include <pcl/point_types.h> #include <pcl/visualization/pcl_visualizer.h> #include <pcl/visualization/cloud_viewer.h> #include <pcl/common/common_headers.h> #include <pcl/io/io.h> #include <pcl/point_types.h> #include <pcl/io/ply_io.h> #include <pcl/io/obj_io.h> #include <pcl/PolygonMesh.h> #include <pcl/point_cloud.h> #include <pcl/io/vtk_lib_io.h> #include "pcl_utils.h" using namespace std; using namespace Eigen; using namespace cv; using namespace pcl; int main(int argc, char **argv) { string filename = "point_data/"; vector<String> files_json; //存放文件路径 glob(filename, files_json, true); // 使用智能指针,创建一个空点云。这种指针用完会自动释放。 PointCloud<PointXYZRGB>::Ptr cloud(new PointCloud<PointXYZRGB>); // PointCloud<PointXYZRGB>::Ptr cloud_sum(new PointCloud<PointXYZRGB>); // for (int i = 0; i < files_json.size(); i++) // { // cout << "name : " << files_json[i] << endl; // pcl::io::loadPCDFile(files_json[i], *cloud); // *cloud_sum = *cloud_sum + *cloud; // cloud->points.clear(); // cout << "sum " << i << " / " << files_json.size() << "done" << endl; // } // pcl::io::savePCDFile("cloud_sum.pcd", *cloud_sum); boost::shared_ptr<pcl::visualization::PCLVisualizer> viewer(new pcl::visualization::PCLVisualizer("3D Viewer")); viewer->setBackgroundColor(0, 0, 0); for (int i = 2; i < files_json.size(); i++) { boost::property_tree::ptree pose_pt = Utils::loadPoseFile(files_json[i]); string name = pose_pt.get<string>("name"); cout << "name : " << name << endl; // string global_name = pose_pt.get<string>("global_name"); std::vector<Eigen::Vector3d> RGB_color; if (!Utils::getRGBcolor(pose_pt, RGB_color)) ; std::vector<Eigen::Vector3d> points; if (!Utils::getXYZpoints(pose_pt, points)) ; cout << "read date done.." << endl; // cout << "global_name : " << global_name << endl; // cout << "RGB_color_size : " << RGB_color.size() << endl; // cout << "points_size : " << points.size() << endl; for (int j = 0; j < RGB_color.size(); j++) { pcl::PointXYZRGB point; point.x = points[j](0); point.y = points[j](1); point.z = points[j](2); point.b = RGB_color[j](2); point.g = RGB_color[j](1); point.r = RGB_color[j](0); cloud->push_back(point); } cout << i << "point number :" << cloud->points.size() << endl; String ss = "pointcloud_" + name + ".pcd"; pcl::io::savePCDFile(ss, *cloud); // 清除数据并退出 cloud->points.clear(); cout << "Point cloud saved." << endl; cout << "next pcd reading..." << endl; } cloud->width = 1; cloud->height = cloud->points.size(); depth_cloud->width = 1; depth_cloud->height = cloud->points.size(); pcl::visualization::PointCloudColorHandlerRGBField<pcl::PointXYZRGB> rgb_cloud(cloud); viewer->addPointCloud<pcl::PointXYZRGB>(cloud, rgb_cloud, "sample cloud"); viewer->setPointCloudRenderingProperties(pcl::visualization::PCL_VISUALIZER_POINT_SIZE, 2, "sample cloud"); viewer->addCoordinateSystem(1.0); while (!viewer->wasStopped()) { viewer->spinOnce(100); boost::this_thread::sleep(boost::posix_time::microseconds(100000)); } cv::waitKey(0); viewer->removeAllPointClouds(); return 0; }
由此可以生成以文件为单位的点云数据,取其中一个生成的点云如图:
程序中注释的部分为最后将所有的点云pcd文件合成一个点云的代码,最后Area_1的整体点云效果如图:
本人i7-8700HQ+16g内存仍然很卡。
之前一直在用这种方式做,调了整整两天的程序终于调通了,结果发现数据中的depth很有问题,合成的图片深度分层很严重,而且分层比较均匀,不像是程序的问题。采用的方法是通过读取data文件夹下的pose.json文件获取对应的相机位姿,再根据相机内参,将depth投影到空间去,并附上rgb信息。然而最后因结果不好而放弃。且自己合成点云非常消耗计算量,电脑跑一会就卡的要死,最好不要采用这种方式,直接使用mat文件中的数据即可。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。