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

news2024/11/14 19:37:45

这两天接了个小任务,需求是替换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 Path

import numpy
import numpy as np
import torch

FILE = 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()))  # relative

from 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 path
        self.imgsz = (640, 640)  # inference size (height, width)
        self.conf_thres = 0.25  # confidence threshold
        self.iou_thres = 0.45  # NMS IOU threshold
        self.max_det = 1000  # maximum detections per image
        self.device = ''  # cuda device, i.e. 0 or 0,1,2,3 or cpu
        self.view_img = False  # show results
        self.save_txt = False # save results to *.txt
        self.save_conf = False  # save confidences in --save-txt labels
        self.save_crop = False  # save cropped prediction boxes
        self.nosave = False  # do not save images/videos
        self.classes = None  # filter by class: --class 0, or --class 0 2 3
        self.agnostic_nms = False  # class-agnostic NMS
        self.augment = False  # augmented inference
        self.visualize = False  # visualize features
        self.update = False  # update all models
        self.project = ROOT / 'runs/predict-seg'  # save results to project/name
        self.name = 'exp'  # save results to project/name
        self.exist_ok = False,  # existing project/name ok, do not increment
        self.line_thickness = 3  # bounding box thickness (pixels)
        self.hide_labels = False  # hide labels
        self.hide_conf = False  # hide confidences
        self.half = False  # use FP16 half-precision inference
        self.dnn = False  # use OpenCV DNN for ONNX inference
        self.vid_stride = 1  # video frame-rate stride
        self.retina_masks = False
        source = str(self.source)
        save_img = not self.nosave and not source.endswith('.txt')  # save inference images
        self.is_file = Path(source).suffix[1:] in (IMG_FORMATS + VID_FORMATS)
        if self.is_file:
            source = check_file(source)  # download
            # Directories
        self.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 model
        self.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.pt
        self.imgsz = check_img_size(self.imgsz, s=self.stride)  # check image size
        # Dataloader
        self.bs = 1  # batch_size
        self.dataset = None
        vid_path, vid_writer = [None] * self.bs, [None] * self.bs

    def GetDynSeg(self, image):

        self.img_size = (640,480)
        im0 = image
        im = letterbox(im0, self.img_size, stride=self.stride, auto=False)[0]  # padded resize
        im = im.transpose((2, 0, 1))[::-1]  # HWC to CHW, BGR to RGB
        im = np.ascontiguousarray(im)
        self.model.warmup(imgsz=(1 if self.pt else self.bs, 3, *self.imgsz))  # warmup
        seen, 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/32
            im /= 255  # 0 - 255 to 0.0 - 1.0
            if len(im.shape) == 3:
                im = im[None]  # expand for batch dim

        # Inference
        with dt[1]:
            pred, proto = self.model(im, augment=self.augment, visualize=False)[:2]

        # NMS
        with 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 image
            seen += 1

            imc = im0.copy() if self.save_crop else im0  # for save_crop

            annotator = 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)  # HWC
                det[:, :4] = scale_boxes(im.shape[2:], det[:, :4], im0.shape).round()  # rescale boxes to im0 size

                # Segments
                if self.save_txt:
                    segments = reversed(masks2segments(masks))
                    segments = [scale_segments(im.shape[2:], x, im0.shape).round() for x in segments]

                # Print results
                for c in det[:, 5].unique():
                    n = (det[:, 5] == c).sum()  # detections per class

                # Mask plotting
                annotator.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 class
                    mask=masks_[:,:,j]
                    mask=np.squeeze(mask,-1)
                    if(c==0 ):
                        newmask[mask == 1] = 1
                    import scipy.io as io
                    torch.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.coloradmin.cn/o/57506.html

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

相关文章

HTML5期末大作业:基于html+css+javascript+jquery实现藏族文化15页【学生网页设计作业源码】

🎉精彩专栏推荐 💭文末获取联系 ✍️ 作者简介: 一个热爱把逻辑思维转变为代码的技术博主 💂 作者主页: 【主页——🚀获取更多优质源码】 🎓 web前端期末大作业: 【📚毕设项目精品实战案例 (10…

免费搜索vs付费搜索:百度谷歌的有力竞争者刚刚出现!

北大出版社,人工智能原理与实践 人工智能和数据科学从入门到精通 详解机器学习深度学习算法原理 人工智能原理与实践 全面涵盖人工智能和数据科学各个重要体系经典 搜索引擎的游戏刚刚被改变! 人们对昨天(12月1号)OpenAI 发布…

UltraISO 制作U盘启动盘

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

[附源码]Python计算机毕业设计Django基于协同过滤的资讯推送平台

项目运行 环境配置: Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术: django python Vue 等等组成,B/S模式 pychram管理等等。 环境需要 1.运行环境:最好是python3.7.7,…

MyBatis动态SQL多表操作

动态SQL if-where标签 <select id"selByCondition" resultMap"rm">select *from mybatis<where><if test"status !null">and STATUS#{STATUS}</if><if test"companyName !null and companyName !">an…

idea10个常用的Debug技巧

文章目录一 回到上一步二 字段断点三 Stream调试四 表达式结果查看五 debug筛选条件六 异常断点七 远程调试八 强制返回九 运行时修改变量十 多线程调试重用快捷键一 回到上一步 进行代码调试的过程中&#xff0c;有的时候由于自己点击下一步的速度比较快&#xff0c;可能之前…

世界连续动作预测模型-方向模型

🍿*★,*:.☆欢迎您/$:*.★* 🍿 正文 <

[附源码]Python计算机毕业设计Django基于java的社区管理系统

项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等等。 环境需要 1.运行环境&#xff1a;最好是python3.7.7&#xff0c;…

云原生k8s的金箍棒

如果云原生是我们喜欢的《西游记》中孙悟空&#xff0c;那Autoscaling就是云原生手中的金箍棒。想象一下&#xff0c;没有金箍棒的孙悟空&#xff0c;还能到处降妖伏魔么&#xff1f;还能成为斗战圣佛吗&#xff1f; Autoscaling 根据需要随时动态扩缩容&#xff0c;有了它&…

TsingHua:FPT: Improving Prompt Tuning Efficiency via Progressive Training

这篇文章我觉得做的也挺有意思的。 是在探究提示学习中渐进式的更新参数比一窝蜂的直接更新参数效果要佳。 开头 是从比较PT&#xff08;prompt learning和fine tuning&#xff09;开始的。为什么PT的收敛速度慢&#xff0c;训练效率低下&#xff1f; 因为PT中中可训练的参数…

[附源码]计算机毕业设计新冠疫苗接种预约系统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…

第15章 基数法则

第15章 基数法则 15.1 通过其他计数来计算当前计数 如何计算拥挤的房间里有多少人?你可以数人头&#xff0c;因为一个人就只有一个头。或者&#xff0c;也可以数耳朵&#xff0c;然后除以2。我们往往可以通过对其他事物计数进而计算当前计数。 最直截了当的通过查找一种事物…

Kotlin高仿微信-第34篇-支付-向商家付款(二维码)

Kotlin高仿微信-项目实践58篇详细讲解了各个功能点&#xff0c;包括&#xff1a;注册、登录、主页、单聊(文本、表情、语音、图片、小视频、视频通话、语音通话、红包、转账)、群聊、个人信息、朋友圈、支付服务、扫一扫、搜索好友、添加好友、开通VIP等众多功能。 Kotlin高仿…

这么简单,还不会使用java8 stream流的map()方法吗?

一、前言 在日常的开发工作中经常碰到要处理list中数据的问题&#xff0c;比如从数据库中查出了很多学生&#xff0c;由于一些原因需要在内存中找出这些学生中的所有姓名&#xff0c;或者把名为“王五”的语文成绩暂时修改为“100”&#xff0c;这些问题怎么处理呐&#xff0c…

初始C语言-1(数据类型、变量、常量、变量的作用域和生命周期、字符串+转义字符+注释)

目录 一、C语言 C语言主要运用于底层&#xff0c;也可以运用于上层软件&#xff08;早期还没有其他的语言的时候&#xff0c;很多游戏就是C语言做的&#xff09; C语言发展至今都是排行前三的计算机语言。 随着物联网&#xff0c;万物互联&#xff0c;以及嵌入式开发和单片机…

Java 面向对象的【三大特征】,你都掌握了吗

文章目录前言一、封装1.封装的概念2.访问修饰限定符3.初识 “ 包 ”4. static 成员static修饰成员变量static修饰成员方法static成员初始化二、继承1.为什么要继承2.继承的概念3.语法4.父类成员访问1.子类中访问父类的成员变量2.子类中访问父类的成员方法5. super 关键字6. 子类…

RabbitMQ之单机多实例部署

单机版安装前面介绍过了&#xff0c;不再介绍。 此处在单机版基础上 &#xff0c;也就是一台Linux虚拟机上启动多个RabbitMQ实例&#xff0c;部署集群。 1、在单个Linux虚拟机上运行多个RabbitMQ实例&#xff1a; 多个RabbitMQ使用的端口号不能冲突多个RabbitMQ使用的磁盘存…

李宏毅《DLHLP》学习笔记6 - 语言模型

视频链接&#xff1a;https://www.youtube.com/watch?vdymfkWtVUdo&listPLJV_el3uVTsO07RpBYFsXg-bN5Lu0nhdG&index8&ab_channelHung-yiLee 课件链接&#xff1a;https://speech.ee.ntu.edu.tw/~tlkagk/courses/DLHLP20/ASR3.pdf 1. Language Model LM的作用是预…

嵌入式Linux 开发经验:注册一个 misc 设备

前言 之前买过好几本Linux 设备驱动的书&#xff0c;不过对设备驱动一知半解&#xff0c;什么叫设备&#xff0c;什么又叫驱动&#xff1f;最近工作需要&#xff0c;从源码级别深入的研究了一下 Linux 下的设备与驱动的概念&#xff0c;略有所收获 一般提起驱动开发&#xff0…

[附源码]Python计算机毕业设计Django基于Java的图书购物商城

项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等等。 环境需要 1.运行环境&#xff1a;最好是python3.7.7&#xff0c;…