YOLO11改进|卷积篇|引入线性可变形卷积LDConv

在这里插入图片描述

目录

    • 一、【LDConv】卷积
      • 1.1【LDConv】卷积介绍
      • 1.2【LDConv】核心代码
    • 二、添加【LDConv】卷积
      • 2.1STEP1
      • 2.2STEP2
      • 2.3STEP3
      • 2.4STEP4
    • 三、yaml文件与运行
      • 3.1yaml文件
      • 3.2运行成功截图

一、【LDConv】卷积

1.1【LDConv】卷积介绍

在这里插入图片描述

下图是【LDCNV】的结构图,让我们简单分析一下运行过程和优势

  • 工作流程:
  • 输入处理(Input):输入是一个大小为 𝐶×𝐻×𝑊的特征图。
  • 卷积生成偏移量(Conv2d for Offset Generation):通过一次常规卷积操作(Conv2D)来生成对应的 偏移量(Offsets)。这些偏移量的形状为 2𝑁×𝐻×𝑊,其中 𝑁表示采样点的数量(通常是卷积核大小的平方,如3x3卷积核对应9个点)。生成的偏移会调整特征图中每个位置的采样点。
  • 生成采样点(Generating Sample Points):使用一个基准采样网格,这个网格基于常规卷积核位置的坐标定义。然后,利用之前生成的偏移量对这些采样点进行调整,形成修正后的采样点。
  • Resample(重采样):对于每个输入点,在其修正后的坐标上进行特征的采样,这就是“Deformable”卷积的核心机制。在每个卷积核的操作中,使用修正后的采样点来替代原本的固定采样点。
  • 卷积和激活(Convolution and Activation):完成采样后,经过卷积操作,并附加常规的归一化(Normalization) 和 激活(Activation,如SiLU),生成输出特征图。
  • 偏移坐标的计算流程(Offset Calculation Process):在下面的图中展示了如何将初始的采样点与偏移量相加,得到修正后的坐标。这些修正后的坐标决定了如何对输入特征图进行采样,确保每个点的采样位置根据输入内容动态变化。
  • 优势:
  • 动态感知:传统卷积在处理图像时,采样位置是固定的,限制了它对形变或非规则几何结构的适应能力。而偏移卷积通过引入动态采样点,能够自适应调整每个采样点的坐标,使得模型在面对形变、不规则目标时,依然能保持良好的特征提取能力。
  • 提升空间建模能力:由于偏移卷积允许采样点在二维空间内自由移动,这使得它可以捕捉到更复杂的空间依赖关系,尤其是那些传统卷积难以处理的局部信息(例如边界或角落的特征)。
  • 提高特征表达能力:修正采样点的位置,可以让卷积操作更精准地聚焦于感兴趣的区域,提高特征图中的重要信息的表达和捕捉能力。
  • 增强模型的鲁棒性:在面对目标发生旋转、缩放或其他形变时,偏移卷积提供了额外的灵活性,确保特征提取过程不受形变影响。这使得模型在处理各种复杂场景时具有更好的鲁棒性在这里插入图片描述

1.2【LDConv】核心代码

import torch.nn as nn
import torch
from einops import rearrange
import mathclass LDConv(nn.Module):def __init__(self, inc, outc, num_param, stride=1, bias=None):super(LDConv, self).__init__()self.num_param = num_paramself.stride = strideself.conv = nn.Sequential(nn.Conv2d(inc, outc, kernel_size=(num_param, 1), stride=(num_param, 1), bias=bias),nn.BatchNorm2d(outc),nn.SiLU())  # the conv adds the BN and SiLU to compare original Conv in YOLOv5.self.p_conv = nn.Conv2d(inc, 2 * num_param, kernel_size=3, padding=1, stride=stride)nn.init.constant_(self.p_conv.weight, 0)self.p_conv.register_full_backward_hook(self._set_lr)@staticmethoddef _set_lr(module, grad_input, grad_output):grad_input = (grad_input[i] * 0.1 for i in range(len(grad_input)))grad_output = (grad_output[i] * 0.1 for i in range(len(grad_output)))def forward(self, x):# N is num_param.offset = self.p_conv(x)dtype = offset.data.type()N = offset.size(1) // 2# (b, 2N, h, w)p = self._get_p(offset, dtype)# (b, h, w, 2N)p = p.contiguous().permute(0, 2, 3, 1)q_lt = p.detach().floor()q_rb = q_lt + 1q_lt = torch.cat([torch.clamp(q_lt[..., :N], 0, x.size(2) - 1), torch.clamp(q_lt[..., N:], 0, x.size(3) - 1)],dim=-1).long()q_rb = torch.cat([torch.clamp(q_rb[..., :N], 0, x.size(2) - 1), torch.clamp(q_rb[..., N:], 0, x.size(3) - 1)],dim=-1).long()q_lb = torch.cat([q_lt[..., :N], q_rb[..., N:]], dim=-1)q_rt = torch.cat([q_rb[..., :N], q_lt[..., N:]], dim=-1)# clip pp = torch.cat([torch.clamp(p[..., :N], 0, x.size(2) - 1), torch.clamp(p[..., N:], 0, x.size(3) - 1)], dim=-1)# bilinear kernel (b, h, w, N)g_lt = (1 + (q_lt[..., :N].type_as(p) - p[..., :N])) * (1 + (q_lt[..., N:].type_as(p) - p[..., N:]))g_rb = (1 - (q_rb[..., :N].type_as(p) - p[..., :N])) * (1 - (q_rb[..., N:].type_as(p) - p[..., N:]))g_lb = (1 + (q_lb[..., :N].type_as(p) - p[..., :N])) * (1 - (q_lb[..., N:].type_as(p) - p[..., N:]))g_rt = (1 - (q_rt[..., :N].type_as(p) - p[..., :N])) * (1 + (q_rt[..., N:].type_as(p) - p[..., N:]))# resampling the features based on the modified coordinates.x_q_lt = self._get_x_q(x, q_lt, N)x_q_rb = self._get_x_q(x, q_rb, N)x_q_lb = self._get_x_q(x, q_lb, N)x_q_rt = self._get_x_q(x, q_rt, N)# bilinearx_offset = g_lt.unsqueeze(dim=1) * x_q_lt + \g_rb.unsqueeze(dim=1) * x_q_rb + \g_lb.unsqueeze(dim=1) * x_q_lb + \g_rt.unsqueeze(dim=1) * x_q_rtx_offset = self._reshape_x_offset(x_offset, self.num_param)out = self.conv(x_offset)return out# generating the inital sampled shapes for the LDConv with different sizes.def _get_p_n(self, N, dtype):base_int = round(math.sqrt(self.num_param))row_number = self.num_param // base_intmod_number = self.num_param % base_intp_n_x, p_n_y = torch.meshgrid(torch.arange(0, row_number),torch.arange(0, base_int))p_n_x = torch.flatten(p_n_x)p_n_y = torch.flatten(p_n_y)if mod_number > 0:mod_p_n_x, mod_p_n_y = torch.meshgrid(torch.arange(row_number, row_number + 1),torch.arange(0, mod_number))mod_p_n_x = torch.flatten(mod_p_n_x)mod_p_n_y = torch.flatten(mod_p_n_y)p_n_x, p_n_y = torch.cat((p_n_x, mod_p_n_x)), torch.cat((p_n_y, mod_p_n_y))p_n = torch.cat([p_n_x, p_n_y], 0)p_n = p_n.view(1, 2 * N, 1, 1).type(dtype)return p_n# no zero-paddingdef _get_p_0(self, h, w, N, dtype):p_0_x, p_0_y = torch.meshgrid(torch.arange(0, h * self.stride, self.stride),torch.arange(0, w * self.stride, self.stride))p_0_x = torch.flatten(p_0_x).view(1, 1, h, w).repeat(1, N, 1, 1)p_0_y = torch.flatten(p_0_y).view(1, 1, h, w).repeat(1, N, 1, 1)p_0 = torch.cat([p_0_x, p_0_y], 1).type(dtype)return p_0def _get_p(self, offset, dtype):N, h, w = offset.size(1) // 2, offset.size(2), offset.size(3)# (1, 2N, 1, 1)p_n = self._get_p_n(N, dtype)# (1, 2N, h, w)p_0 = self._get_p_0(h, w, N, dtype)p = p_0 + p_n + offsetreturn pdef _get_x_q(self, x, q, N):b, h, w, _ = q.size()padded_w = x.size(3)c = x.size(1)# (b, c, h*w)x = x.contiguous().view(b, c, -1)# (b, h, w, N)index = q[..., :N] * padded_w + q[..., N:]  # offset_x*w + offset_y# (b, c, h*w*N)index = index.contiguous().unsqueeze(dim=1).expand(-1, c, -1, -1, -1).contiguous().view(b, c, -1)x_offset = x.gather(dim=-1, index=index).contiguous().view(b, c, h, w, N)return x_offset#  Stacking resampled features in the row direction.@staticmethoddef _reshape_x_offset(x_offset, num_param):b, c, h, w, n = x_offset.size()x_offset = rearrange(x_offset, 'b c h w n -> b c (h n) w')return x_offset

二、添加【LDConv】卷积

2.1STEP1

首先找到ultralytics/nn文件路径下新建一个Add-module的python文件包【这里注意一定是python文件包,新建后会自动生成_init_.py】,如果已经跟着我的教程建立过一次了可以省略此步骤,随后新建一个LDConv.py文件并将上文中提到的注意力机制的代码全部粘贴到此文件中,如下图所示在这里插入图片描述

2.2STEP2

在STEP1中新建的_init_.py文件中导入增加改进模块的代码包如下图所示在这里插入图片描述

2.3STEP3

找到ultralytics/nn文件夹中的task.py文件,在其中按照下图添加在这里插入图片描述

2.4STEP4

定位到ultralytics/nn文件夹中的task.py文件中的def parse_model(d, ch, verbose=True): # model_dict, input_channels(3)函数添加如图代码,【如果不好定位可以直接ctrl+f搜索定位】

在这里插入图片描述

三、yaml文件与运行

3.1yaml文件

以下是添加【LDConv】注意力机制在Backbone中的yaml文件,大家可以注释自行调节,效果以自己的数据集结果为准

# Ultralytics YOLO 🚀, AGPL-3.0 license
# YOLO11 object detection model with P3-P5 outputs. For Usage examples see https://docs.ultralytics.com/tasks/detect# Parameters
nc: 80 # number of classes
scales: # model compound scaling constants, i.e. 'model=yolo11n.yaml' will call yolo11.yaml with scale 'n'# [depth, width, max_channels]n: [0.50, 0.25, 1024] # summary: 319 layers, 2624080 parameters, 2624064 gradients, 6.6 GFLOPss: [0.50, 0.50, 1024] # summary: 319 layers, 9458752 parameters, 9458736 gradients, 21.7 GFLOPsm: [0.50, 1.00, 512] # summary: 409 layers, 20114688 parameters, 20114672 gradients, 68.5 GFLOPsl: [1.00, 1.00, 512] # summary: 631 layers, 25372160 parameters, 25372144 gradients, 87.6 GFLOPsx: [1.00, 1.50, 512] # summary: 631 layers, 56966176 parameters, 56966160 gradients, 196.0 GFLOPs# YOLO11n backbone
backbone:# [from, repeats, module, args]- [-1, 1, Conv, [64, 3, 2]] # 0-P1/2- [-1, 1, LDConv, [128,3,2]] # 1-P2/4- [-1, 2, C3k2, [256, False, 0.25]]- [-1, 1, LDConv, [256,3,2]] # 3-P3/8- [-1, 2, C3k2, [512, False, 0.25]]- [-1, 1, LDConv, [512,3,2]] # 5-P4/16- [-1, 2, C3k2, [512, True]]- [-1, 1, LDConv, [1024,3,2]] # 7-P5/32- [-1, 2, C3k2, [1024, True]]- [-1, 1, SPPF, [1024, 5]] # 9- [-1, 2, C2PSA, [1024]] # 10# YOLO11n head
head:- [-1, 1, nn.Upsample, [None, 2, "nearest"]]- [[-1, 6], 1, Concat, [1]] # cat backbone P4- [-1, 2, C3k2, [512, False]] # 13- [-1, 1, nn.Upsample, [None, 2, "nearest"]]- [[-1, 4], 1, Concat, [1]] # cat backbone P3- [-1, 2, C3k2, [256, False]] # 16 (P3/8-small)- [-1, 1, Conv, [256, 3, 2]]- [[-1, 13], 1, Concat, [1]] # cat head P4- [-1, 2, C3k2, [512, False]] # 19 (P4/16-medium)- [-1, 1, Conv, [512, 3, 2]]- [[-1, 10], 1, Concat, [1]] # cat head P5- [-1, 2, C3k2, [1024, True]] # 22 (P5/32-large)- [[16, 19, 22], 1, Detect, [nc]] # Detect(P3, P4, P5)

以上添加位置仅供参考,具体添加位置以及模块效果以自己的数据集结果为准

3.2运行成功截图

在这里插入图片描述

OK 以上就是添加【LDConv】卷积的全部过程了,后续将持续更新尽情期待

在这里插入图片描述

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

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

相关文章

JumperServer入门

一、安装部署 官方安装文档:快速入门 - JumpServer 文档 机器准备 CentOS7 ip 角色 192.168.252.145 主节点 192.168.252.146 被控节点1 192.168.252.148 被控节点2 安装JumperServer curl -sSL https://resource.fit2cloud.com/jumpserver/jumpserver…

集合框架03:List接口介绍及使用

1.视频链接:13.08 List接口使用(1)_哔哩哔哩_bilibilihttps://www.bilibili.com/video/BV1zD4y1Q7Fw?p8&vd_sourceb5775c3a4ea16a5306db9c7c1c1486b5 2.代码示例 package com.yundait.Demo01;import java.util.ArrayList; import java…

Final Glory推出“荣耀勋章-神龙”,推动游戏叙事范式发展

GameFi赛道因基建设施的缺失而长期处于加密市场的边缘位置,该叙事在市场中的占有率正在下降。不过好的一面是,随着MetaArena引擎面向市场,正在推动区块链游戏市场的叙事向全新的范式发展。 MetaArena引擎是以零知识证明方案为基础的Web3游戏基…

实现一个计算器的功能(一般形式、函数指针数组的形式、回调函数的形式)

实现一个计算器的功能&#xff1a; 一般的形式&#xff1a; #include<stdio.h> int Add(int x, int y) {return x y; } int Sub(int x, int y) {return x - y; } int Mul(int x, int y) {return x * y; } int Div(int x, int y) {return x / y; } void menu() {printf…

Java中TreeMap,HashMap和LinkedHashMap的区别

先决条件&#xff1a;Java 中的 HashMap 和 TreeMap TreeMap、HashMap 和 LinkedHashMap&#xff1a;有什么相似之处&#xff1f; 所有类都提供键->值映射和遍历键的方法。这些类之间最重要的区别是时间保证和键的顺序。 HashMap、TreeMap 和LinkedHashMap三个类都实现了…

【数据结构】【队列】算法汇总

一、顺序队列【相当于一维数组】 1.准备工作 #define MAXQSIZE 100 typedef struct{QElemType*base;int front;int rear; }SqQueue; 2.队满&#xff0c;队空。入队&#xff0c;出队 二、链式队列 1.准备工作 typedef struct Qnode{ElemType data;struct Qnode*next; }Qnod…

Github优质项目推荐 - 第五期

文章目录 Github优质项目推荐 - 第五期一、【localsend】&#xff0c;47.5k stars - 附近设备文件互传二、【Pake】&#xff0c;29.9k stars - 网页变成桌面应用三、【laravel-crm】&#xff0c;10.7k stars - CRM 解决方案四、【localstack】&#xff0c;55.7k stars - 本地 A…

RabbitMQ(学习前言)

目录 学习MQ之前有必要先去温故下微服务知识体系&#xff0c;以加深本章节的理解 一、微服务间的通讯方式 1. 基本介绍 2. 同步通讯 2.1. 什么是同步通讯 2.2. 同步通讯存在的问题 问题一&#xff1a;耦合度高 问题二&#xff1a;性能和吞吐能力下降 问题三&#xff1a…

时序必读论文16|ICLR24 CARD:通道对齐鲁棒混合时序预测Transformer

论文标题&#xff1a;CARD: Channel Aligned Robust Blend Transformer for Time Series Forecasting 论文链接&#xff1a;https://arxiv.org/abs/2305.12095 代码链接&#xff1a;https://github.com/wxie9/CARD 前言 Transformer取得成功的一个关键因素是通道独立&#…

SpringBoot框架下旅游管理系统的创新设计与实现

第二章 相关技术简介 2.1 JAVA技术 本次系统开发采用的是面向对象的Java作为软件编程语言&#xff0c;Java表面上很像C&#xff0c;但是Java仅仅是继承了C的某些优点&#xff0c;程序员很少使用的C语言的特征在Java设计中去掉了。Java编程语言并没有什么结构&#xff0c;它把数…

Arduino UNO R3自学笔记21 之 Arduino电机的闭环控制(PID)

注意&#xff1a;学习和写作过程中&#xff0c;部分资料搜集于互联网&#xff0c;如有侵权请联系删除。 前言&#xff1a;上篇写了电机速度测定&#xff0c;这篇主要是讲测定出的速度用于反馈&#xff0c;使得实际速度快速响应到需要的速度。 1.控制系统介绍 分2大类&#x…

​​​​​​​如何使用Immersity AI将图片转换成3D效果视频

随着技术的进步&#xff0c;图片处理变得越来越强大和直观。借助Immersity AI这样的工具&#xff0c;我们现在可以轻松地将平面图片转换成3D效果视频。以下是如何使用Immersity AI进行这一转换的详细步骤。 第一步&#xff1a;访问Immersity AI网站 首先&#xff0c;打开你的…

Spring开发最佳实践之跨域处理

1. 跨域处理 1.1 异常现象 1.2 异常原因分析 跨源资源共享的官方定义如下&#xff1a; 跨源资源共享&#xff08;CORS&#xff0c;Cross Origin Resource Sharing。或通俗地译为跨域资源共享&#xff09;是一种基于 HTTP 头的机制&#xff0c;该机制通过允许服务器标示除了它自…

在mac中通过ip连接打印机并实现双面打印

首先需要找到电脑自带的打印。添加打印机。 填写好打印机的ip地址&#xff0c;然后添加。 填写好ip地址后&#xff0c;直接添加就行 添加完打印机后其实就可以打印了。但是有些功能可能实现不了&#xff0c;比如说双面打印。为了实现双面打印的功能&#xff0c;需要再进行设置…

Vue83 引入elementUI

笔记 安装插件 安装按需引入插件 代码 ### App.vue <template><div><button>原生的按钮</button><input type"text"><atguigu-row><atguigu-button>默认按钮</atguigu-button><atguigu-button type"pr…

Arduino UNO R3自学笔记22 之 Arduino基础篇学习总结

注意&#xff1a;学习和写作过程中&#xff0c;部分资料搜集于互联网&#xff0c;如有侵权请联系删除。 前言&#xff1a;目前将Arduino的大多数基础内容学习了&#xff0c;做个总结。 1.编程语言 学习单片机&#xff0c;在面向单片机编程时&#xff0c;语言是最基础的&#…

localhost与127.0.0.1傻傻分不清楚,区别详解来了

对应程序员来说&#xff0c;localhost和127.0.0.1经常使用&#xff0c;但是却又傻傻分不清楚&#xff01;尽管它们在实际应用中经常互换使用&#xff0c;但它们之间确实存在一些细微的差别。本文我将详细探讨localhost与127.0.0.1的区别。 一、定义与解析方式 localhost 定…

SSM外卖点餐软件APP-计算机毕业设计源码30768

目 录 摘要 1 绪论 1.1 研究背景 1.2研究目的 1.3论文结构与章节安排 2 外卖点餐软件APP系统分析 2.1 可行性分析 2.1.1 技术可行性分析 2.1.2 经济可行性分析 2.1.3 操作可行性分析 2.2 系统流程分析 2.2.1 数据流程 3.3.2 业务流程 2.3 系统功能…

旅游管理自动化:SpringBoot系统设计与实现

第二章 相关技术简介 2.1 JAVA技术 本次系统开发采用的是面向对象的Java作为软件编程语言&#xff0c;Java表面上很像C&#xff0c;但是Java仅仅是继承了C的某些优点&#xff0c;程序员很少使用的C语言的特征在Java设计中去掉了。Java编程语言并没有什么结构&#xff0c;它把数…