DynaSLAM代码详解(3) — MaskNet.cc加载Mask R-CNN网络部分

news2024/9/22 0:35:31

目录

3.1 Mask R-CNN运行

3.2 SegmentDynObject::SegmentDynObject()

3.3 SegmentDynObject::GetSegmentation()


3.1 Mask R-CNN运行

在Examples/RGB-D/rgbd_tum.cc文件开始运行Mask R-CNN网络,首先进入MaskNet->GetSegmentation函数。

        // Segment out the images
        // 开始进行图像分割
        cv::Mat mask = cv::Mat::ones(480,640,CV_8U);
        if (argc == 6 || argc == 7)
        {
            cv::Mat maskRCNN;
            // 利用GetSegmentation()函数进行图像分割
            maskRCNN = MaskNet->GetSegmentation(imRGB,string(argv[5]),vstrImageFilenamesRGB[ni].replace(0,4,""));
            // 将分割的结果 maskRCNN 复制到 maskRCNNdil
            cv::Mat maskRCNNdil = maskRCNN.clone();
            // 对 maskRCNN 应用膨胀操作,使用 kernel 作为内核
            cv::dilate(maskRCNN,maskRCNNdil, kernel);
            // 将 maskRCNNdil 从 mask 中减去,得到最终的mask结果
            mask = mask - maskRCNNdil;
        }

3.2 SegmentDynObject::SegmentDynObject()

(1) SegmentDynObject()函数的主要功能是加载网络的配置文件和初始化网络。

SegmentDynObject::SegmentDynObject(){
    std::cout << "Importing Mask R-CNN Settings..." << std::endl;
    //调用ImportSettings()函数加载Mask R-CNN网络设置
    ImportSettings();
    std::string x;
    //设置环境变量PYTHONPATH,通过/src/python文件夹设置为this->py_path
    setenv("PYTHONPATH", this->py_path.c_str(), 1);
    //获取环境变量PYTHONPATH的值,并将其赋值给变量x。
    x = getenv("PYTHONPATH");
    //初始化Python解释器
    Py_Initialize();

    //创建一个新的NDArray转换器
    this->cvt = new NDArrayConverter();

    //通过Pylmport_ImportModule方法读入src/python目录下的MaskRCNN.py文件
    this->py_module = PyImport_ImportModule(this->module_name.c_str());
    //查py_module是否为空,如果为空则终止程序
    assert(this->py_module != NULL);

    //通过PyObject_GetAttrString方法导入模块(MaskRCNN.py)中的方法或类
    this->py_class = PyObject_GetAttrString(this->py_module, this->class_name.c_str());
    //检查py_class是否为空,如果为空则终止程序
    assert(this->py_class != NULL);

    //使用py_class创建一个新的Python实例,并将其赋值给net变量
    this->net = PyInstance_New(this->py_class, NULL, NULL);
    //检查net是否为空,如果为空则终止程序
    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);
}

首先做的就是通过ImportSettings加载Mask R-CNN网络配置:

void SegmentDynObject::ImportSettings(){
    std::string strSettingsFile = "./Examples/RGB-D/MaskSettings.yaml";
    cv::FileStorage fs(strSettingsFile.c_str(), cv::FileStorage::READ);

    fs["py_path"] >> this->py_path;     // src/python目录
    fs["module_name"] >> this->module_name; // MaskRCNN文件
    fs["class_name"] >> this->class_name;   //Mask类
    fs["get_dyn_seg"] >> this->get_dyn_seg;     //MaskRCNN中的方法获取mask信息

    // std::cout << "    py_path: "<< this->py_path << std::endl;
    // std::cout << "    module_name: "<< this->module_name << std::endl;
    // std::cout << "    class_name: "<< this->class_name << std::endl;
    // std::cout << "    get_dyn_seg: "<< this->get_dyn_seg << std::endl;
}

主要是加载了几个参数:

  • py_path:src/python目录

  • module name:MaskRCNN文件

  • class_name:Mask类

  • get_dyn_seg:GetDynSeg MaskRCNN中的方法获取mask信息

# 获取mask信息
def GetDynSeg(image,image2=None):
	h = image.shape[0]
	w = image.shape[1]
	if len(image.shape) == 2:
		im = np.zeros((h,w,3))
		im[:,:,0]=image
		im[:,:,1]=image
		im[:,:,2]=image
		image = im
	#if image2 is not None:
	#	args+=[image2]
	# Run detection
	results = model.detect([image], verbose=0)
	# Visualize results
	r = results[0]
	i = 0
	mask = np.zeros((h,w))
	for roi in r['rois']:
		if class_names[r['class_ids'][i]] == 'person':
			image_m = r['masks'][:,:,i]
			mask[image_m == 1] = 1.
		if class_names[r['class_ids'][i]] == 'bicycle':
			image_m = r['masks'][:,:,i]
			mask[image_m == 1] = 1.
		if class_names[r['class_ids'][i]] == 'car':
			image_m = r['masks'][:,:,i]
			mask[image_m == 1] = 1.
		if class_names[r['class_ids'][i]] == 'motorcycle':
			image_m = r['masks'][:,:,i]
			mask[image_m == 1] = 1.
		if class_names[r['class_ids'][i]] == 'airplane':
			image_m = r['masks'][:,:,i]
			mask[image_m == 1] = 1.
		if class_names[r['class_ids'][i]] == 'bus':
			image_m = r['masks'][:,:,i]
			mask[image_m == 1] = 1.
		if class_names[r['class_ids'][i]] == 'train':
			image_m = r['masks'][:,:,i]
			mask[image_m == 1] = 1.
		if class_names[r['class_ids'][i]] == 'truck':
			image_m = r['masks'][:,:,i]
			mask[image_m == 1] = 1.
		if class_names[r['class_ids'][i]] == 'boat':
			image_m = r['masks'][:,:,i]
			mask[image_m == 1] = 1.
		if class_names[r['class_ids'][i]] == 'bird':
			image_m = r['masks'][:,:,i]
			mask[image_m == 1] = 1.
		if class_names[r['class_ids'][i]] == 'cat':
			image_m = r['masks'][:,:,i]
			mask[image_m == 1] = 1.
		if class_names[r['class_ids'][i]] == 'dog':
			image_m = r['masks'][:,:,i]
			mask[image_m == 1] = 1.
		if class_names[r['class_ids'][i]] == 'horse':
			image_m = r['masks'][:,:,i]
			mask[image_m == 1] = 1.
		if class_names[r['class_ids'][i]] == 'sheep':
			image_m = r['masks'][:,:,i]
			mask[image_m == 1] = 1.
		if class_names[r['class_ids'][i]] == 'cow':
			image_m = r['masks'][:,:,i]
			mask[image_m == 1] = 1.
		if class_names[r['class_ids'][i]] == 'elephant':
			image_m = r['masks'][:,:,i]
			mask[image_m == 1] = 1.
		if class_names[r['class_ids'][i]] == 'bear':
			image_m = r['masks'][:,:,i]
			mask[image_m == 1] = 1.
		if class_names[r['class_ids'][i]] == 'zebra':
			image_m = r['masks'][:,:,i]
			mask[image_m == 1] = 1.
		if class_names[r['class_ids'][i]] == 'giraffe':
			image_m = r['masks'][:,:,i]
			mask[image_m == 1] = 1.		
		i+=1
	#print('GetSeg mask shape:',mask.shape)

	return maskk

(2) 然后设置环境变量,设置环境变量PYTHONPATH,通过/src/python文件夹设置为this->py_path  ,然后将环境变量的值赋值给x。

//设置环境变量PYTHONPATH,通过/src/python文件夹设置为this->py_path
setenv("PYTHONPATH", this->py_path.c_str(), 1);

setenvi起到改变或增加环境变量的作用,用法如下:

int setenv(const char *name,const char value,int overwrite);
  • name:为环境变量名称字符串。
  • value:为变量内容。
  • overwrite:用来决定是否要改变已存在的环境变量。如果overwrite不为0,则改变环境变量原有内容,原有内容会被改为参数value所指的变量内容。如果overwrite:为O,且该环境变量已有内容,则参数value会被忽略。
  • reuturn:执行成功则返回0,有错误发生时返回-1。

 (3) 然后初始化Python解释器,创建一个NDArray转换器。

//初始化Python解释器
Py_Initialize();
//创建一个新的NDArray转换器
this->cvt = new NDArrayConverter();

(4) 然后进行一些列的模型的导入和检查,最后调用GetSegmentation函数对该张图片进行处理。

    //通过Pylmport_ImportModule方法读入src/python目录下的MaskRCNN.py文件
    this->py_module = PyImport_ImportModule(this->module_name.c_str());
    //查py_module是否为空,如果为空则终止程序
    assert(this->py_module != NULL);

    //通过PyObject_GetAttrString方法导入模块(MaskRCNN.py)中的方法或类
    this->py_class = PyObject_GetAttrString(this->py_module, this->class_name.c_str());
    //检查py_class是否为空,如果为空则终止程序
    assert(this->py_class != NULL);

    //使用py_class创建一个新的Python实例,并将其赋值给net变量
    this->net = PyInstance_New(this->py_class, NULL, NULL);
    //检查net是否为空,如果为空则终止程序
    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);

3.3 SegmentDynObject::GetSegmentation()

 函数的主要功能是获取图像的分割结果  。 

  • 首先读取目录路径和文件名指定的图像文件,将图像转换为Python的NDArray类型,因为Mask R-CNN是python语言编写,图像格式要满足网络要求。
  • 然后将图像传递给Mask R-CNN网络进行处理,将分割结果转换为cv::Mat格式,进一步将分割结果转换为CV_8U,即将数据类型转换为8位无符号整数,其中0表示背景,1表示前景。
  • 最后判断路径是否安全,如果安全则首先尝试打开目录,如果目录不存在,则创建目录;将分割结果保存为目录路径和文件名指定的图像文件。
/*
 *  获取图像的分割结果
*/
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()){
        // 图像转换为Python的NDArray类型
        PyObject* py_image = cvt->toNDArray(image.clone());
        assert(py_image != NULL);
        // 将图像传递给网络进行处理
        PyObject* py_mask_image = PyObject_CallMethod(this->net, const_cast<char*>(this->get_dyn_seg.c_str()),"(O)",py_image);
        // 将分割结果转换为cv::Mat格式
        seg = cvt->toMat(py_mask_image).clone();
        // 将分割结果转换为CV_8U,即将数据类型转换为8位无符号整数,其中0表示背景,1表示前景。
        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;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/740032.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

使用Dockerfile创建nginx+php镜像,采用分层

什么是Dockerfile Dockerfile是一种能被Docker程序解释的脚本&#xff0c;它是由一条条的命令所组成&#xff0c;每条命令对应Linux下面的一条命令&#xff0c;Docker程序将这些Dockerfile命令翻译成真正的Linux命令 Dockerfile命令 Dockerfile通常会包含如下命令&#xff1a…

【AGC】认证服务HarmonyOS(api9)实现手机号码认证登录

【问题背景】 近期AGC上线了HarmonyOS(api9)平台的SDK&#xff0c;这样api9的设备也能使用认证服务进行快速认证登录了。下面为大家带来如何使用auth SDK&#xff08;api9&#xff09;实现手机号码认证登录。 【开通服务】 1.登录AppGallery Connect&#xff0c;点击“我的项…

lc202306

785. 判断二分图 对于单个连通图&#xff1a;一个dfs判断图中所有节点符合二分。 遍历节点列表>遍历所有连通图。 133. clone graph 994. rotting oranges 力扣 维护一个time表&#xff0c;表示所有orange rot的最快时间。对每一个 t0 就 rot 的 orange dfs&#xff0c;遇…

无法从gcr.io获取distroless镜像问题

当我们能够访问外网&#xff0c;且能够ping通gcr.io网站后&#xff0c;依旧无法拉取distroless镜像时&#xff0c;可以通过以下网站作为中转获取。 rootacoinfo-Vostro-3667:/home/xxx/xx# docker pull gcr.io/distroless/base-debian11 Using default tag: latest Error resp…

快速制作优惠券信息展示小程序教程

要想拥有一个拥有优惠券功能的小程序商城&#xff0c;首先我们需要搭建一个小程序。以乔拓云第三方平台为例&#xff0c;我们可以通过以下步骤来完成。 首先&#xff0c;登录乔拓云平台&#xff0c;进入【乔拓云】后台管理页面。乔拓云功能强大&#xff0c;不仅可以搭建小程序…

运维开发面试题第五期(华电天益)

1、一个目录(没有子目录)有很多文件&#xff0c;想最快速度查看到最近更新的文件你有几种方式实现?请写出一种或几种 ls -lrt 目录 R 逆序 l 长格式 t 按更新时间排序2、使用 tar 命令打包/etc 目录下的所有文件(包括子文件夹) tar -cvf 打包路径加名字 /etc/ 仅打包…

[gtp]购物车案例参考

react hooks,购物车案例. 在列表上点击或者-更新数量,调用接口更新单个价格. 点击table的checkbox勾选后,计算总价? 对于React Hooks和购物车案例&#xff0c;您可以使用useState来管理列表中商品的数量和总价。当点击"“或”-"按钮时&#xff0c;可以更新相应商品…

网络营销的定义、实现方式、关键要素和应用案例

网络营销是通过互联网及相关技术手段来实现企业品牌推广、产品销售、客户维护等目标的营销方式。近年来&#xff0c;随着互联网技术的飞速发展&#xff0c;网络营销已成为企业推广、销售和宣传的重要手段。本文将从网络营销的定义、实现方式、关键要素和应用案例等方面&#xf…

【ECharts系列】ECharts 图表渲染问题解决方案

1 问题描述 echats 渲染&#xff0c;第一次的时候只出现Y轴数值&#xff0c;不出现X轴数值&#xff0c;切换下页面&#xff0c;X轴数值就能出现。 2 原因分析 如果在使用ECharts渲染时&#xff0c;X轴数值只在切换页面后才出现&#xff0c;可能是因为ECharts在初始化时没有正确…

Mac上提取应用APP的LOGO

1、找到想提取LOGO的应用&#xff0c;右键「显示包内容」 2、 双击【Contents】文件夹&#xff0c;再双击【Resources】文件夹 3、双击图标打开&#xff0c;选择最清晰的一帧&#xff0c;右键【导出为】 4、选择保存位置&#xff0c;格式注意选择常见格式&#xff0c;如png

【Ajax】Express 服务端框架

因为Ajax需要向服务端发送请求。Express框架比较简单&#xff0c;内容使用起来比较少&#xff0c;借助一个基本功能就可以了。 Express 基于 Node.js 平台&#xff0c;快速、开放、极简的 Web 开发框架 所以需要安装一下node.js 检查命名&#xff1a;node -v 安装 打开项目最外…

多线程面试题详解

总体概览 线程的基础知识 线程和进程的区别&#xff1f; 并行和并发有什么区别&#xff1f; 创建线程的方式有哪些&#xff1f; runable和callable有什么区别 run()和start()有什么区别 线程包括了那些状态&#xff1f;这些状态之间如何变化 新建T1,T2,T3三个线程&#xff0c;如…

C#内存不够解决方法

今天在使用C#程序的时候&#xff0c;出现了下图的问题&#xff1a; 注意下图中我用红框标出的位置&#xff0c;实际是一个三维数组。 但是出现这个问题和三维数组没有关系。 他是提示内存不足。 百度了一下&#xff0c;C#在生成的过程中如果是生成对应的32位系统&#xff0c…

VMware15.5版本虚拟机安装Linux Centos 7系统详细步骤

1.首先准备好Centos7.6安装文件&#xff0c;安装文件可百度搜索或在阿里镜像站中下载。 阿里巴巴开源镜像站-OPSX镜像站-阿里云开发者社区 2.新建虚拟机. 1选择自定义&#xff0c;点下一步。 2硬件兼容性选择15.x&#xff0c;&#xff0c;点下一步。 3选择稍后安装操作系统&…

自定义seg_decoder组件并创建Nios系统(一)

前面进行了数码管的显示 对Avalon总线协议进行了大概的学习 那么就可以 将数码管译码器模块封装成符合Avalon-MM接口的组件创建一个基于Nios Ⅱ处理器的系统 将数码管译码器组件添加至该系统中 通过用户应用程序控制数码管显示字符0~F 本文同数码管显示一样并不是完整项目&a…

JavaWeb_瑞吉外卖_项目优化Day12-前后端分离

JavaWeb_瑞吉外卖_项目优化Day12-前后端分离 前后端分离开发介绍开发流程前端技术栈 YapiSwagger介绍使用方式常用注解 项目部署部署架构部署环境说明部署前端项目部署后端项目 来源 前后端分离开发 介绍 开发流程 前端技术栈 开发工具 Visual Studio Codehbuilder 技术框架 …

【全栈开发指南】VUE前端路由设计及配置

我们在使用Vue.js时&#xff0c;创建单页面应用一定会用到路由&#xff0c;Vue Router 是 Vue.js 官方的路由管理器&#xff0c;我们在开发框架中过程中&#xff0c;需要结合Vue Router路由管理器提供的功能&#xff0c;设计和实现系统中菜单的配置。 一、实现原理 一级菜单r…

idea创建webapp文件夹

结果的图片&#xff1a; 第一步&#xff1a; file-》project structure 第二步&#xff1a; 修改路径&#xff0c;点击右侧“Deloyment descriptors”下面的笔进行修改。 // 增加了src\main // web修改为了webapp C:\Users\www12\Desktop\huwantiku2\src\main\webapp\WEB-IN…

计算机图形学 3D 渲染 笔记(二)

一、阴影 判断一个点是否被遮住&#xff0c;可以从该点像光源方向发射射线&#xff08;P tL&#xff09;&#xff0c;若射线被与物体发生相交&#xff0c;则说明它在阴影中。而这个物体由于要在 P 和 光源之间&#xff0c;在方向光场景下&#xff0c; t 的取值范围是 0 < …

vue3+vite+Ts 基于Antv/x6 绘制流程图

需求效果&#xff1a; 需求&#xff1a; 实现一个流程图&#xff0c;双击可对相应的组件进行一些功能操作&#xff1b; 工具栈&#xff1a; 这里使用antv/x6&#xff0c; 基于vue3vitets进行开发 官网地址&#xff1a; https://x6.antv.antgroup.com/examples/showcase/pra…