目录
1.执行例程rgbd_tum
2.SegmentDynObject::SegmentDynObject方法
3. SegmentDynObject::GetSegmentation
4.初始化SLAM系统
/home/lhwnb/Desktop/slam/DynaSLAM/Examples/RGB-D/rgbd_tum /home/lhwnb/Desktop/slam/DynaSLAM/Vocabulary/ORBvoc.txt /home/lhwnb/Desktop/slam/DynaSLAM/Examples/RGB-D/TUM1.yaml /home/lhwnb/Desktop/slam/DynaSLAM/dataset/rgbd_dataset_freiburg1_xyz/ /home/lhwnb/Desktop/slam/DynaSLAM/dataset/assciation.txt /home/lhwnb/Desktop/slam/DynaSLAM/dataset/mask/ /home/lhwnb/Desktop/slam/DynaSLAM/dataset/output/
执行例程的时候输入到CLion中的程序实参是这样的:
分别对应着RGB例程的可执行文件、ORB字典的路径、相机的配置文件、数据集、深度图和RGB图的对齐文件、mask目录(可选)、output目录(可选)。
如果不指定mask目录和output目录,则程序的执行和ORB-SLAM2无区别。
通过LoadImage函数将RGB图像读入vstrImageFilenamesRGB中,深度图读入vstrImageFilenamesD中,时间戳读入vTimestamps中。
随后测试Mask R-CNN网络是否可用:
// Initialize Mask R-CNN DynaSLAM::SegmentDynObject *MaskNet; if (argc==6 || argc==7) { cout << "Loading Mask R-CNN. This could take a while..." << endl; MaskNet = new DynaSLAM::SegmentDynObject(); cout << "Mask R-CNN loaded!" << endl; }
%YAML:1.0 py_path: "./src/python/" module_name: "MaskRCNN" class_name: "Mask" get_dyn_seg: "GetDynSeg"
主要是加载了几个参数:
@py_path : src/python目录
@module_name : MaskRCNN文件
@get_dyn_seg:GetDynSeg MaskRCNN.py中Mask类的方法
SegmentDynObject::SegmentDynObject(){ std::cout << "Importing Mask R-CNN Settings..." << std::endl; ImportSettings(); std::string x; setenv("PYTHONPATH", this->py_path.c_str(), 1); x = getenv("PYTHONPATH"); Py_Initialize(); this->cvt = new NDArrayConverter(); this->py_module = PyImport_ImportModule(this->module_name.c_str()); assert(this->py_module != NULL); this->py_class = PyObject_GetAttrString(this->py_module, this->class_name.c_str()); assert(this->py_class != NULL); this->net = PyInstance_New(this->py_class, NULL, NULL); assert(this->net != NULL); std::cout << "Creating net instance..." << std::endl; cv::Mat image = cv::Mat::zeros(480,640,CV_8UC3); //Be careful with size!! std::cout << "Loading net parameters..." << std::endl; GetSegmentation(image); }
SegmentDynObject::SegmentDynObject方法是加载Mask R-CNN网络的参数并测试网络是否有效并实例化GetDynSeg方法,如果python部分没配置正确的画在这里会报段错误。
setenv起到改变或增加环境变量的作用,用法如下:
int setenv(const char *name,const char * value,int overwrite);
@name为环境变量名称字符串。
@value则为变量内容。@overwrite用来决定是否要改变已存在的环境变量。
如果overwrite不为0,则改变环境变量原有内容,原有内容会被改为参数value所指的变量内容。如果overwrite为0,且该环境变量已有内容,则参数value会被忽略。
@return 执行成功则返回0,有错误发生时返回-1。
这是例子:#include
main() { char * p; if((p=getenv(“USER”))) printf(“USER =%s\n”,p); setenv(“USER”,”test”,1); printf(“USER=%s\n”,getenv(“USEr”)); unsetenv(“USER”); printf(“USER=%s\n”,getenv(“USER”)); } 执行结果:USER = root USER = test USER = (null)
py_module 的类型是PyObject *类型,通过PyImport_ImportModule方法读入src/python目录下的MaskRCNN.py文件,如果读入文件为空报错。
py_class 的类型是PyObject *类型,通过PyObject_GetAttrString方法导入已导入模块(MaskRCNN.py)中的方法或类(MaskRCNN.py中的Mask类)。
net 的类型是PyObject *类型,通过PyInstance_New方法使用类构造对象。
这样我们顺利地构造了MaskRCNN.py中的Mask类。
下面我们创建网络实例:Creating net instance....,首先创建一个480*640的空白图像。
调用GetSegmentation函数对该张图片进行处理。
cv::Mat SegmentDynObject::GetSegmentation(cv::Mat &image,std::string dir, std::string name){ cv::Mat seg = cv::imread(dir+"/"+name,CV_LOAD_IMAGE_UNCHANGED); if(seg.empty()){ PyObject* py_image = cvt->toNDArray(image.clone()); assert(py_image != NULL); PyObject* py_mask_image = PyObject_CallMethod(this->net, const_cast
(this->get_dyn_seg.c_str()),"(O)",py_image); seg = cvt->toMat(py_mask_image).clone(); seg.cv::Mat::convertTo(seg,CV_8U);//0 background y 1 foreground if(dir.compare("no_save")!=0){ DIR* _dir = opendir(dir.c_str()); if (_dir) {closedir(_dir);} else if (ENOENT == errno) { const int check = mkdir(dir.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH); if (check == -1) { std::string str = dir; str.replace(str.end() - 6, str.end(), ""); mkdir(str.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH); } } cv::imwrite(dir+"/"+name,seg); } } return seg; } 本方法将传入的image调用MaskRCNN.py中的GetDynSeg方法进行语义分割,得到动态掩码图。
首先将image图片转换成tensor格式存储在py_image在,判断是否读取成功。
通过PyObject_CallMethod方法调用(this -> net 是MaskRCNN.py中Mask类实例化的一个对象,this->get_dyn_seg 是该类中的一个方法求得图像的mask信息,再将其转化成图片格式保存起来。返回图像。
现在Mask R-CNN网络初始化完毕,屏幕输出Mask net loaded!。
这部分和双目相同,详情见博客:
DynaSLAM-8 DynaSLAM中双目运行流程(Ⅱ):初始化SLAM系统部分System.cchttps://blog.csdn.net/qq_41694024/article/details/128843822 初始化
// Dilation settings int dilation_size = 15; cv::Mat kernel = getStructuringElement(cv::MORPH_ELLIPSE, cv::Size( 2*dilation_size + 1, 2*dilation_size+1 ), cv::Point( dilation_size, dilation_size ) );
关于Dilate它的本质是取邻域的最大值(是和像素值有关的)。
if (argc==7) { std::string dir = string(argv[6]); mkdir(dir.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH); dir = string(argv[6]) + "/rgb/"; mkdir(dir.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH); dir = string(argv[6]) + "/depth/"; mkdir(dir.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH); dir = string(argv[6]) + "/mask/"; mkdir(dir.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH); }
如果输入的参数是7个,即调用Mask R-CNN网络的情况下,创建几个目录: