络腮胡菲菲 发表于 2025-1-9 21:55:34

一文详解YOLOv8多模态目标检测(可见光+红外图像,基于Ultralytics官方代码

1. 文章紧张内容

       本文紧张是详解YOLOv8实现多模态,包罗怎样启动,以及详细代码部分怎样改进,从而让单模态的检测支持为多模态的检测!。基于YOLO的单模态检测赛道已经非常卷,很难出好的论文,这个时候入门多模态检测是非常有须要的!以是,本篇代码分析论文则是入门基于YOLOv8的多模态目标检测的基础之一。
2. 相关说明

       本篇博文代码来源于原博客:YOLOV8多模态(可见光+红外光目标检测任务,基于Ultralytics官方代码实现)。
       原博客中使用的是基于Ultralytics的YOLOv8模型,使用的数据集是DroneVehicle,这里的DroneVehicle数据集是红外-可见光两种模态的无人机目标检测数据集。需要注意的是:原数据集中的DroneVehicle数据图像有白边,需要对原数据集进行去白边进行处置惩罚。别的,我自己在这里把目标框从旋转框改为程度框,也就是仅仅进行程度框的检测,后续再考虑出一篇旋转框的检测内容。
       注意到:以下代码的相关内容分析需要前提知识:已经了解单模态的YOLOv8代码相关的知识点。
3. 基于YOLOv8的多模态目标检测

       这一块分为两个部分,第一块是启动运行部分,第二块是多模态代码的分析(中期融合,也叫做特性融合),第二块是重点,因为后续想改进代码必须搞懂怎样进行模型改进和前向传播的改进等。
3.1 启动运行YOLOv8多模态代码

       从上面原博客中找到代码的地址,或者直接点击这个链接TwoStream_Yolov8源代码,进去看相关README部分,设置好相关环境,然后预备好相关的数据集DroneVehicle以及对应的格式摆放。别的在安装环境的时候一定要运行这个代码pip install -e .,这个代码的作用是将这个项目TwoStream_Yolov8的本地的Ultralytics文件夹进行编译,而不是用环境nn下对应的包。不然就会出现No module Ultralytics相关错误。别的上述编译代码是在项目标根目次进行运行的,各人别搞错。
3.2 详解代码流程(重点)

       这一块的内容紧张是从train函数部分,一步步去分析怎样构造多模态目标检测的(这里是中期融合,后续的前期融合我预备再出一篇分析),这里先给出一张函数的流程图,下面的内容就是根据这张图来说明,注意我不会讲所有的代码,只会讲牵涉多模态相关需要修改的代码部分。
https://i-blog.csdnimg.cn/direct/417ebe22a1eb4031bead3f7de5cc103b.jpeg
3.2.1 train.py文件(入口)

       说明:作者也提供了一份train.py文件,我是用自己的train.py,大差不差。源代码加载yaml文件使用的是绝对路径,我这里通过sys.path.append(“/home/project/TwoStream_Yolov8-main/”),将根目次设定为项目标根目次路径,以是下面加载yaml文件使用相对路径即可!然后,device部分我这里是多卡训练(使用Linux环境,发起使用Linux服务器),如果你是单卡的话改成0即可!
       代码分析:首先加载YOLO模型,这个YOLO模型只是ultralytics/model/yolo/model.py文件中的一个类,这个类继承了Model基类,也就是engine/model.py(这个类是重点)。以是你可以理解第一行代码model只是将yaml文件加载到了基类engine/model.py中的cfg变量当中。
       背面第二行代码,调用model.train函数,其中带了data属性,也就是数据集的yaml文件!如下面第二幅图所示:train、train_ir分别为可见光和红外图像的训练集路径。
       注意这里和源代码差别,我这里改了相关代码,紧张在路径中的imgRGB和IR部分,如果你也想改为自定义的路径,需要修改ultralytics/data/base.py中的load_image代码,如第三幅图所示。其紧张的作用是根据可见光的路径获取红外文件的路径,然后再加载数据。
import warnings
import sys
sys.path.append("/home/project/TwoStream_Yolov8-main/")
warnings.filterwarnings('ignore')
from ultralytics import YOLO

if __name__ == '__main__':

    # 加载模型
    model = YOLO('yaml/ADDyolov8n.yaml') # .load('yolov8n.pt')# 从YAML构建并转移权重
    # 训练模型
    results = model.train(data='data/drone2.yaml', epochs=200, batch=32, device=)
https://i-blog.csdnimg.cn/direct/da5c8de96f034b21a204b98670831416.png
https://i-blog.csdnimg.cn/direct/4be90408cbcb434f9b884cf8ed95237c.png
3.2.2 engine\model.py文件

       进入到train这个类中,就跳转到了engine\model.py,然后我们找到在这里self.trainer.train()代码,继承进入,这里注意到我们进入的是下面这个类。
https://i-blog.csdnimg.cn/direct/ac6c9203bee64a6d974d4299d9c5c301.png
3.2.3 engine\trainer.py文件

       进入到engine\trainer.py类,找到这一行代码:self._do_train(world_size),进入这个方法,需要注意到world_size是判断训练是几张卡,如果有两张,那么假设你batch_size设置为16,每张卡就是batch_size为8.
       然后再找到这一行代码:self._setup_train(world_size),再次进入找到 ckpt = self.setup_model()方法,然后再次进入可以看到self.model = self.get_model(cfg=cfg, weights=weights, verbose=RANK == -1) 代码,这里的cfg就是我们的yaml/ADDyolov8n.yaml。
3.2.4 models\yolo\detect\train.py文件

       然后再次进入跳转到models\yolo\detect\train.py文件,可以看到model = DetectionModel(cfg, nc=self.data["nc"], verbose=verbose and RANK == -1)这一行代码,说明我们的model使用的是DetectionModel类。
3.2.5 nn\tasks.py文件

       通过DetectionModel进入到这个nn\tasks.py文件,然后找到这行代码self.model, self.save = parse_model(deepcopy(self.yaml), ch=ch, verbose=verbose),再进入到parse_model这个函数中,这个parse_model就是通过yaml文件去构造model的结构。
       第一:我们可以看到这两行代码:tx的list表里存放的是输入的通道数,接近着会讲,ty为索引,初始值为0.
tx= # TODO....
ty=0
       第二:然后可以看到如下几行的代码:联合上面tx和ty的定义可以知道,这是对输入通道数c1的改变。当yaml文中from也就是f值为-4的时候,输入的通道数要从tx当中去取出,并且当ty不即是0的时候需要乘于width因子。
c1, c2 = ch, args
            if f==-4:
                c1=tx
                if ty!=0:
                  c1=c1*width
            
                c1=int(c1)
                ty+=1
       第三:来联合ADDyolov8n.yaml文件中的代码联合来看,如下所示。可以看出,第一次出现f=-4的时候,是在IR也就是红外分支Conv的时候,如果这个时候我们不用特别分支进行判断,按照YOLOv8的原逻辑就会从上一层也就是f=-1处置惩罚,此时的c1=256,也就是RGB第四层Conv的输出,明显不对。因为IR分支的第一层输入应该也是3,以是我们就搞懂了上述逻辑的代码,这里是一个重点!,这样我们就构造了通过yaml新建model的逻辑。
# Ultralytics YOLO
页: [1]
查看完整版本: 一文详解YOLOv8多模态目标检测(可见光+红外图像,基于Ultralytics官方代码