YOLOv8改进——引入可变形卷积DCNv3

news/2024/7/11 0:44:58 标签: YOLO, YOLOv8, DCNv3, 可变形卷积

YOLOv8 详解
✨✨✨YOLOv8详解 【网络结构+代码+实操】
可变形卷积DCNv1 & DCNv2
✨✨✨论文及代码详解——可变形卷积(DCNv1)
✨✨✨论文及代码详解——可变形卷积(DCNv2)
DCNv3InternImage中提出的,DCNv3在DCNv2版本上进行了改进。
✨✨✨论文详解——《InternImage: Exploring Large-Scale Vision Foundation Models with Deformable Convolutions》
✨✨✨ 代码详解——可变形卷积DCNv3

本文只讲解在YOLOv8的代码中添加DCNv3的操作流程, 具体的原理参见上述的链接~

1. 下载ops_dcnv3

如下图,首先下载InterImage官方代码,然后在segmentation、detection、classification文件夹下均可以找到ops_dcnv3文件夹,该文件夹下的内容就是实现DCNv3算子的核心代码。
在这里插入图片描述

  • modules
    如下图所示, modules文件夹中的dcnv3.py文件主要定义了DCNv3模块。
    其中DCNv3_pytorchDCNv3的pytorch实现版本,DCNv3DCNv3的C++实现版本。
    在这里插入图片描述
  • functions
    如下图所示,function文件夹中的dcnv3_func.py文件定义了DCNv3的一些核心操作。
    其中黄色部分的DCNv3Function类被c++版本的DCNv3 调用。
    其中红色部分的dcnv3_core_pytorch方法被pytorch版本的DCNv3_pytorch调用。
    在这里插入图片描述
  • src
    src下的代码是用C++来实现DCNv3中核心操作,其下的cpucuda分别表示cpu和cuda编程两种实现版本。c++实现的版本需要去编译,否则如上图所示,黄色箭头指向的import DCNv3 有红色波浪线,无法正常导入。
    如果想import DCNv3成功,有两种解决办法:
    (1)需要编译:DCNv3具体编译方法是直接运行make.sh文件(但是这种方法很容易编译失败,对于pytorch,cuda的版本以及c++编译器的配置都有要求)
    (2)不需要编译:去官网上下载轮子https://github.com/OpenGVLab/InternImage/releases/tag/whl_files (更推荐这种方法,但是也需要注意cuda和pytorch的版本)
    在这里插入图片描述
    然后将ops_dcnv3复制到ultralutics文件夹下。
    在这里插入图片描述

DCNv3_36">2. 添加DCNv3模块

打开modules.py文件。
在这里插入图片描述
首先从ops_dcnv3 中导入DCNv3DCNv3_pytorch
其中DCNv3是C++实现版本,必须先在上一步编译成功,或者安装好了轮子,否则会报错。
DCNv3_pytorch 是pytorch实现的版本,只要基础的pytorch环境安装正确就不会出错。
但是在实际的训练过程中,C++版本的运行速度更快,推荐使用C++版本。

from ..ops_dcnv3.modules import DCNv3,DCNv3_pytorch
  • DCNv3_YOLO
    然后在modules.py文件中添加DCNv3_YOLO模块。其中self.dcnv3即可以使用c++版本的DCNv3,也可以使用pytorch版本实现的DCNv3_pytorch。
class DCNV3_YoLo(nn.Module):
    def __init__(self, inc, ouc, k=1, s=1, p=None, g=1, d=1, act=True):
        super().__init__()
        
        self.conv = Conv(inc, ouc, k=1)
        self.dcnv3 = DCNv3(ouc, kernel_size=k, stride=s, group=g, dilation=d) # c++版本
        # self.dcnv3 = DCNv3_pytorch(ouc, kernel_size=k, stride=s, group=g, dilation=d) # pytorch版本
        self.bn = nn.BatchNorm2d(ouc)
        self.act = Conv.default_act
    
    def forward(self, x):
        x = self.conv(x)
        x = x.permute(0, 2, 3, 1)
        x = self.dcnv3(x)
        x = x.permute(0, 3, 1, 2)
        x = self.act(self.bn(x))
        return x
  • Bottleneck_DCNV3
    把原始的Bottleneck中的self.cv2Conv换成DCNV3_YOLO
    在这里插入图片描述
    具体代码如下:
class Bottleneck_DCNV3(nn.Module):
    # Standard bottleneck
    def __init__(self, c1, c2, shortcut=True, g=1, k=(3, 3), e=0.5):  # ch_in, ch_out, shortcut, groups, kernels, expand
        super().__init__()
        c_ = int(c2 * e)  # hidden channels
        self.cv1 = Conv(c1, c_, k[0], 1)
        self.cv2 = DCNV3_YoLo(c_, c2, k[1], 1, g=g)
        self.add = shortcut and c1 == c2
 
    def forward(self, x):
        return x + self.cv2(self.cv1(x)) if self.add else self.cv2(self.cv1(x))

  • C2f_DCNV3
    把原始C2f中的Bottleneck换成Bottleneck_DCNv3
    在这里插入图片描述
    具体代码如下:
class C2f_DCNV3(nn.Module):
    # CSP Bottleneck with 2 convolutions
    def __init__(self, c1, c2, n=1, shortcut=False, g=1, e=0.5):  # ch_in, ch_out, number, shortcut, groups, expansion
        super().__init__()
        self.c = int(c2 * e)  # hidden channels
        self.cv1 = Conv(c1, 2 * self.c, 1, 1)
        self.cv2 = Conv((2 + n) * self.c, c2, 1)  # optional act=FReLU(c2)
        self.m = nn.ModuleList(Bottleneck_DCNV3(self.c, self.c, shortcut, g, k=(3, 3), e=1.0) for _ in range(n))

    def forward(self, x):
        y = list(self.cv1(x).chunk(2, 1))
        y.extend(m(y[-1]) for m in self.m)
        return self.cv2(torch.cat(y, 1))

    def forward_split(self, x):
        y = list(self.cv1(x).split((self.c, self.c), 1))
        y.extend(m(y[-1]) for m in self.m)
        return self.cv2(torch.cat(y, 1))

3. 补充声明

nn/tasks.py中,下图中的列表里添加DCNv3_YOLO,Bottleneck_DCNV3,C2f_DCNV3
在这里插入图片描述
在这里插入图片描述

4. 修改Yaml文件

yolov8s.yaml文件中的C2f修改成C2f_DCNV3, Conv修改成DCNv3_YOLO (具体怎么修改,都可以自己决定,然后通过实验看看效果如何)
在这里插入图片描述


http://www.niftyadmin.cn/n/4958435.html

相关文章

认识这对搭档,解决 90% 的查询问题

在excel里,对于“查找”的实现,vlookup绝对是使用得最为频繁的一个函数。 但是,遇到下面问题,vlookup就没用了。 下面的表格记录了员工的信息,现在想通过“姓名”查找对应的“工号”。如图所示,通过输入不同…

结构型(三) - 享元模式

一、概念 享元模式(Flyweight Pattern):所谓“享元”,顾名思义就是被共享的单元。享元模式的意图是复用对象,节省内存,前提是享元对象是不可变对象。 优点:可以极大地减少内存中对象的数量&am…

ABAP 定义复杂的数据结构

最近有个需求是实现ABAP数据类型与JASON类型的转换。想要创建个ABAP的数据类型来接JASON类型是个挺麻烦的事。例如下面这个JASON数据,是个很简单的数据结构。但对ABAP来说有4层了,就有点复杂了。 不过ABAP的数据类型也是支持直接定义数据结构的嵌套的。如…

smiley-http-proxy-servlet 实现springboot 反向代理,项目鉴权,安全的引入第三方项目服务

背景: 项目初期 和硬件集成,实现了些功能服务,由于是局域网环境,安全问题当时都可以最小化无视。随着对接的服务越来越多,部分功能上云,此时就需要有一种手段可以控制到其他项目/接口的访问权限。 无疑 反向…

MyBatis-Plus快速开始[MyBatis-Plus系列] - 第482篇

悟纤:师傅,MyBatis-Plus被你介绍的这么神乎其乎,咱们还是来的点实际的吧。 师傅:那真是必须的,学习技术常用的一种方法,就是实践。 悟纤:贱贱更健康。 师傅:这… 师傅:…

Linux 多线程中执行fork的情况

一、普通多线程中执行fork的情况 1.多线程中没有执行fork的情况 代码如下&#xff1a; #include<stdio.h> #include<stdlib.h> #include<unistd.h> #include<pthread.h> #include<string.h> #include<semaphore.h>void*fun(void* arg) …

docker启动配置hosts

docker run -d --name gateway --add-hostnacos:[ip] --add-hostrabbitmq:[ip] --net"host" gateway:01

Navicat里.sql文件转换到.db文件

1.在桌面创建一个xxx.db文件&#xff0c;在navicat中创建数据库的时候会用到 2.在navicat创建数据库 在 Navicat 的导航栏中&#xff0c;选择 "工具" -> "SQL 文件执行器"。 在 SQL 文件执行器中&#xff0c;单击 "打开" 按钮&#xff0c;选择…