【学习记录】Dynaslam源代码魔改-替换MaskRCNN为YoloV5

news/2024/5/8 14:07:30/文章来源:https://blog.csdn.net/weixin_43849505/article/details/128157896

这两天接了个小任务,需求是替换Dynaslam里面的动态物体识别模块,将MaskRCNN换为YoloV5,这里记录一下过程中遇见的问题。

一、运行Dynaslam

Dynaslam本身是一个基于ORBSLAM2的视觉SLAM框架,论文并没有仔细看过,简单来说就是在ORBSLAM的基础上,加了一动态物体的滤除,这里的滤除使用了两种策略:基于MaskRCNN和基于视觉几何。既然要替换使用的过滤网络,那么首先就是要跑起来这个Dyanslam,从代码来看,本身还是基于ORBSLAM的,但是加入了神经网络的模块,所以引入了很多Python相关的内容,这里配置主要参照下面的链接:
Dynaslam环境配置与代码替换

大多数的问题按照链接进行修改即可,这里补充一下几个链接里没有的问题:

scikit-image库

这个库主要的问题是明明安装上了但是依然显示找不到库,这里网上查了很多办法,有说换版本的有说更新的,本人用的是下面的指令进行的更新,在两台电脑上都修改成功了。

pip install scikit-image --upgrade --user

运行带有mask版本的Dynaslam

在运行Dyanslam的过程中,如果最后两个参数进行了输入,则表明运行时使用了MaskRCNN进行动态物体的过滤,但是在运行时经常会显示不能初始化,这里经过代码的排查,并不是参数或者设备性能的问题,是Dynaslam特征点提取策略的问题。Dynaslam本身是基于ORBSLAM的,在ORBSLAM的初始化时,要求两张图至少要有500对匹配特征点才可以进行初始化,但是在Dynaslam中,由于对场景内的动态物体进行了过滤,导致在提取特征点时原本出现在动态物体上的特征点被遮挡了,所以达不到ORBSLAM初始化的点对数要求,解决方法有两种,一个是修改yaml文件,让提取ORB特征点的时候尽可能提取更多特征点,另一个方法是直接修改初始化的代码,降低点对数要求,两种方法其实都是要让Dynaslam成功初始化。

二、配置Yolov5环境

这一步没有太大的问题,用anaconda创建一个新环境然后配置就可以了,下载yolov5的源码然后用里面的requirement.txt进行配置即可,需要注意的是,很多的环境都需要挂代理去下载,不挂的话要么龟速要么就直接显示查询不到库文件,关于Ubuntu下面如何配置代理文件可以参考下面的链接:Ubuntu环境下配置clash代理

三、代码的魔改

将MaskRCNN替换,其实本来并不是一个很麻烦的内容,从Dynaslam代码来看,只要修改调用的Python文件就可以了,改之前我也是这么想的,但改的过程啥错误都出来了。

Yolov5封装

在改Dynaslam之前,首先要把Yolov5的代码进行封装,具体来说就是让原本predict.py里面通过主函数调用的方法,转换为通过对象进行的调用,这里主要是涉及一些Python基础语法的问题,并且原本通过命令行读取参数的部分现在也用不上了,需要删除一部分函数,最后为了与Dynaslam的接口相对应,需要将传递的参数进行更换,不再使用文件名进行读取,而是直接传递一个numpy的图像。这里放一下封装好的Yolov5,要改的只有一个predict.py,其余并没有什么变化,使用时初始化一个Mask对象并调用GetDynSeg函数传递一张图像即可。

import argparse
import os
import platform
import sys
from pathlib import Pathimport numpy
import numpy as np
import torchFILE = Path(__file__).resolve()
ROOT = FILE.parents[1]  # YOLOv5 root directory
if str(ROOT) not in sys.path:sys.path.append(str(ROOT))  # add ROOT to PATH
ROOT = Path(os.path.relpath(ROOT, Path.cwd()))  # relativefrom models.common import DetectMultiBackend
from utils.dataloaders import IMG_FORMATS, VID_FORMATS, LoadImages, LoadScreenshots, LoadStreams
from utils.general import (LOGGER, Profile, check_file, check_img_size, check_imshow, check_requirements, colorstr, cv2,increment_path, non_max_suppression, print_args, scale_boxes, scale_segments,strip_optimizer, xyxy2xywh)
from utils.plots import Annotator, colors, save_one_box
from utils.segment.general import masks2segments, process_mask
from utils.torch_utils import select_device, smart_inference_mode
from utils.augmentations import (Albumentations, augment_hsv, classify_albumentations, classify_transforms, copy_paste,cutout, letterbox, mixup, random_perspective)class Mask(object):def __init__(self):self.weights = ROOT / 'yolov5m-seg.pt'  # model.pt path(s)self.source = ROOT / 'data/images' # file/dir/URL/glob/screen/0(webcam)self.data = ROOT / 'data/coco128.yaml'  # dataset.yaml pathself.imgsz = (640, 640)  # inference size (height, width)self.conf_thres = 0.25  # confidence thresholdself.iou_thres = 0.45  # NMS IOU thresholdself.max_det = 1000  # maximum detections per imageself.device = ''  # cuda device, i.e. 0 or 0,1,2,3 or cpuself.view_img = False  # show resultsself.save_txt = False # save results to *.txtself.save_conf = False  # save confidences in --save-txt labelsself.save_crop = False  # save cropped prediction boxesself.nosave = False  # do not save images/videosself.classes = None  # filter by class: --class 0, or --class 0 2 3self.agnostic_nms = False  # class-agnostic NMSself.augment = False  # augmented inferenceself.visualize = False  # visualize featuresself.update = False  # update all modelsself.project = ROOT / 'runs/predict-seg'  # save results to project/nameself.name = 'exp'  # save results to project/nameself.exist_ok = False,  # existing project/name ok, do not incrementself.line_thickness = 3  # bounding box thickness (pixels)self.hide_labels = False  # hide labelsself.hide_conf = False  # hide confidencesself.half = False  # use FP16 half-precision inferenceself.dnn = False  # use OpenCV DNN for ONNX inferenceself.vid_stride = 1  # video frame-rate strideself.retina_masks = Falsesource = str(self.source)save_img = not self.nosave and not source.endswith('.txt')  # save inference imagesself.is_file = Path(source).suffix[1:] in (IMG_FORMATS + VID_FORMATS)if self.is_file:source = check_file(source)  # download# Directoriesself.save_dir = increment_path(Path(self.project) / self.name, exist_ok=self.exist_ok)  # increment run( self.save_dir / 'labels' if self.save_txt else self.save_dir).mkdir(parents=True, exist_ok=True)  # make dir# Load modelself.device = select_device(self.device)self.model = DetectMultiBackend(weights=self.weights, device=self.device, dnn = self.dnn, data=self.data, fp16=self.half)self.stride, self.names, self.pt = self.model.stride, self.model.names, self.model.ptself.imgsz = check_img_size(self.imgsz, s=self.stride)  # check image size# Dataloaderself.bs = 1  # batch_sizeself.dataset = Nonevid_path, vid_writer = [None] * self.bs, [None] * self.bsdef GetDynSeg(self, image):self.img_size = (640,480)im0 = imageim = letterbox(im0, self.img_size, stride=self.stride, auto=False)[0]  # padded resizeim = im.transpose((2, 0, 1))[::-1]  # HWC to CHW, BGR to RGBim = np.ascontiguousarray(im)self.model.warmup(imgsz=(1 if self.pt else self.bs, 3, *self.imgsz))  # warmupseen, windows, dt = 0, [], (Profile(), Profile(), Profile())with dt[0]:im = torch.from_numpy(im).to(self.model.device)im = im.half() if self.model.fp16 else im.float()  # uint8 to fp16/32im /= 255  # 0 - 255 to 0.0 - 1.0if len(im.shape) == 3:im = im[None]  # expand for batch dim# Inferencewith dt[1]:pred, proto = self.model(im, augment=self.augment, visualize=False)[:2]# NMSwith dt[2]:pred = non_max_suppression(pred, self.conf_thres, self.iou_thres, self.classes, self.agnostic_nms,max_det=self.max_det, nm=32)for i, det in enumerate(pred):  # per imageseen += 1imc = im0.copy() if self.save_crop else im0  # for save_cropannotator = Annotator(im0, line_width=self.line_thickness, example=str(self.names))if len(det):masks = process_mask(proto[i], det[:, 6:], det[:, :4], im.shape[2:], upsample=True)  # HWCdet[:, :4] = scale_boxes(im.shape[2:], det[:, :4], im0.shape).round()  # rescale boxes to im0 size# Segmentsif self.save_txt:segments = reversed(masks2segments(masks))segments = [scale_segments(im.shape[2:], x, im0.shape).round() for x in segments]# Print resultsfor c in det[:, 5].unique():n = (det[:, 5] == c).sum()  # detections per class# Mask plottingannotator.masks(masks,colors=[colors(x, True) for x in det[:, 5]],im_gpu=None if self.retina_masks else im[i])masks_ = masks.permute(1, 2, 0)newmask = np.zeros((masks.shape[1], masks.shape[2]))for j, (*xyxy, conf, cls) in enumerate(det[:, :6]):c = int(cls)  # integer classmask=masks_[:,:,j]mask=np.squeeze(mask,-1)if(c==0 ):newmask[mask == 1] = 1import scipy.io as iotorch.set_printoptions(profile="full")return newmask

Dynaslam接口修改

Dynaslam修改,主要还是因为Python版本的问题,原本使用的MaskRCNN是Python2.7版本,换成YoloV5之后是Python3.7版本,所以需要改很多东西,这里很多东西改的稀里糊涂,简单记录一下还有印象的修改内容。

首先是Python的环境问题,在运行时要将原本的conda环境换成运行yolo的conda环境,缺哪些库就安装哪些库,除此之外,要修改Dynaslam里面的cmakelist,将一些原本指向Python2.7的路径换为Python3.7,这一步看似简单,耗费了一晚上的时间,很多路径问题到现在都没有搞清楚,但是代码确实是跑起来了。

其次是版本更换带来的写法问题,这个涉及一些Python和c++联合编程的知识,在c++里面初始化一个Python对象,在Python2.7里面对应的函数是PyMethod_New,但是在Python3.7里,这个函数被换成了PyInstanceMethod_New,如果换了版本,写法上也需要改,这是个大坑,如果对联合编程不熟悉(比如我),很容易忽略这里的错误。
在这里插入图片描述
还有一个印象比较深刻的bug,是调用Python对象的函数时,在c++的接口里预留了好多的函数,都可以实现调用Python对象的函数,不同的函数写法也是不一样的,主要问题在于,如何正确给函数传递self,也就是Python对象自身,在Python程序里,有时候我们需要self参数来读取对象自身的一些参数,但如果我们要通过c++进行调用,这个self的传递就成了个问题,这里我尝试了两种解决方案,一个是在传参时,将对象本身作为一个参数再次传递回去,比如说使用PyObject_CallMethod这个函数,这个函数的第三个参数是指定后续参数的类型,这时我们可以在这个字段加一个O,表示后续的一个参数是一个对象,然后把这个对象设置为自身,那么就相当于将自身传递给了函数,但这种写法会导致程序在运行时不能执行init函数,也就是初始化的对象没有init,进而导致后续的一系列错误,所以尝试的第二种解决方案,就是在创建对象后,单独调用它的构造函数,这里是参考的c++调用Python方法里面的内容,这种写法虽然不知道什么原理,但确实成功了。
在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

期末测试——H5方式练习题

期末考试——H5完成方式——练习题 前言 本练习训练了孩子们的栅格化布局,H5标签,CSS样式,并对列表与菜单进行了强化训练。使孩子们更好的掌握H5布局,为后面的框架教学打好基础。 素材下载地址: 链接:htt…

UltraISO 制作U盘启动盘

1、 从Ubuntu官网http://cn.ubuntu.com/download/下载系统的iso文件 用来制作的U盘需要是FAT32格式的,可以通过格式化U盘更改(注意,如果U盘已经写入过隐藏分区了,需要在磁盘管理里面删除相关隐藏分区然后合并为一个大分区后…

open label file.(This can be normal only if you use MScoco)

E:\yolov4-rubish\darknet\our_data\ImagesAug 把标签的txt文件和Jpg文件放在同一个文件夹

12月2日:thinkphp中数据库完结

数据库的查询 聚合查询 聚合查询的几种方法其中将count作为重点来说,由图所示,即为使用count()方法中需要注意的点 count(*)的使用count()中字段名为具体值的使用方法时间查询 官方文档中列举的是使用wheretime()进行查询的方法,但是在日常的…

C++11标准模板(STL)- 算法(std::set_difference)

定义于头文件 <algorithm> 算法库提供大量用途的函数&#xff08;例如查找、排序、计数、操作&#xff09;&#xff0c;它们在元素范围上操作。注意范围定义为 [first, last) &#xff0c;其中 last 指代要查询或修改的最后元素的后一个元素。 计算两个集合的差集 std:…

历史名人鲁迅介绍HTML个人网页作业作品下载 历史人物介绍网页设计制作 大学生英雄人物网站作业模板 dreamweaver简单个人网页制作

&#x1f389;精彩专栏推荐&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb; ✍️ 作者简介: 一个热爱把逻辑思维转变为代码的技术博主 &#x1f482; 作者主页: 【主页——&#x1f680;获取更多优质源码】 &#x1f393; web前端期末大作业…

【历史上的今天】12 月 3 日:世界上第一条短信;Fortran 语言之父诞生;百度贴吧上线

整理 | 王启隆 透过「历史上的今天」&#xff0c;从过去看未来&#xff0c;从现在亦可以改变未来。 今天是 2022 年 12 月 3 日&#xff0c;在 21 年前的今天&#xff0c;电动平衡车&#xff08;Segway&#xff09;问世&#xff1b;电动平衡车是一种电力驱动、具有自我平衡能力…

Win11的两个实用技巧系列之如何关闭文字热门搜索、任务栏上的应用

目录 in10和Win11 22H2如何关闭文字热门搜索? Win11 22H2关闭文字热门搜索 Win10 22H2关闭文字热门搜索 Win11中如何不用鼠标打开已固定在任务栏上的应用 鼠标的操作方式如下&#xff1a; 点击拿去 in10和Win11 22H2如何关闭文字热门搜索? 不管是Win10还是Win11&#…

Compose 动画艺术探索之属性动画

本篇文章是此专栏的第三篇文章&#xff0c;如果想阅读前两篇文章的话请点击下方链接&#xff1a; Compose 动画艺术探索之瞅下 Compose 的动画Compose 动画艺术探索之可见性动画 Compose的属性动画 属性动画是通过不断地修改值来实现的&#xff0c;而初始值和结束值之间的过…

TensorFlow之文本分类算法-6

1 前言 2 收集数据 3 探索数据 4 选择模型 5 准备数据 6 模型-构建训练评估 构建输出层 构建n-gram模型 构建序列模型 GloVe&#xff08;英文全称是Global Vectors for Word Representation&#xff09;是一个全球化的英语语境的单词表示的向量集&#xff0c;其使用非…

Windows ssh免密访问Linux服务器

文章目录1.在Windows上生成公钥和私钥2.将公钥中的内容复制到linux服务器3.确认linux服务器开启了允许SSH免密登录4.确认免密登录配置成功ssh提供了安全的身份认证的策略&#xff0c;在免密登录之前&#xff0c;首先需要一对公钥和私钥。客户端拿着私钥&#xff0c;服务端拿着公…

HTML网页制作代码——简约的旅游图文相册博客HTML模板(12页)HTML+CSS+JavaScript 静态HTML旅行主题网页作业

&#x1f468;‍&#x1f393;学生HTML静态网页基础水平制作&#x1f469;‍&#x1f393;&#xff0c;页面排版干净简洁。使用HTMLCSS页面布局设计,web大学生网页设计作业源码&#xff0c;这是一个不错的旅游网页制作&#xff0c;画面精明&#xff0c;排版整洁&#xff0c;内容…

了解世界杯赔率,让您运气更‘好‘(个人分享)

足球世界杯买球赢面计算理论基础实际计算用例&#xff1a;代码实现理论基础 假设有两只球队甲和乙&#xff0c;在双方实力局等的情况下&#xff0c;赢球概率都为0.5%&#xff0c;则有&#xff1a; 甲乙概率胜负1/4胜胜1/4负胜1/4负负1/4 由此可知&#xff1a;甲胜的概率是1/4…

亚马逊云科技推出安全数据湖Amazon Security Lake

2022年12月2日&#xff0c;亚马逊云科技在2022 re:Invent全球大会上宣布&#xff0c;推出Amazon Security Lake&#xff0c;该服务可以自动将客户在云端和本地的安全数据集中到客户在亚马逊云科技账户下专门构建的数据湖中&#xff0c;方便客户针对安全数据做出快速行动。 Am…

教你6招轻松搞定 网站被木马反复篡改

提到网络被恶意篡改&#xff0c;应该让很多做了百度竞价的企业官网怀恨已久了吧&#xff1f;这类行为的目的就是通过这些受害网站获得排名并跳转到违法网站&#xff0c;达到不法的目的。对于企业来说不但损失了百度竞价的费用&#xff0c;还对企业形象造成很大的影响。甚至直接…

[附源码]计算机毕业设计springboot云南美食管理系统

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

svg路径动画

前言 最近在开发大屏看板&#xff0c;UI让做一个这样的效果 本来也简单&#xff0c;UI给个git动图放上就好了。但是UI给的图有四五十m&#xff0c;实在是太大了。后来想到了svg路径动画&#xff0c;之前从来没有搞过&#xff0c;就研究了下&#xff0c;由于svg没怎么研究过&a…

实现自定义Spring Boot Starter

实现自定义Spring Boot Starter一、原理二、实战1 自定义 Spring Boot Starter1.1 添加maven依赖1.2 属性类AuthorProperties1.3 自动配置类AuthorAutoConfiguration1.4 业务逻辑AuthorServer1.5 spring.factories2 测试自定义的 Spring Boot Starter2.1 新建module或者新建工程…

Compose 动画艺术探索之动画规格

本篇文章是此专栏的第四篇文章&#xff0c;如果想阅读前三篇文章的话请点击下方链接&#xff1a; Compose 动画艺术探索之瞅下 Compose 的动画Compose 动画艺术探索之可见性动画Compose 动画艺术探索之属性动画 动画规格在上一篇文章中提到过&#xff0c;不过上一篇文章中说的…

[附源码]JAVA毕业设计教材管理(系统+LW)

[附源码]JAVA毕业设计教材管理&#xff08;系统LW&#xff09; 目运行 环境项配置&#xff1a; Jdk1.8 Tomcat8.5 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xf…