在图像去模糊等视觉任务中,传统卷积神经网络(CNNs)因局部感受野的限制难以捕捉全局依赖关系,而 Transformer 虽能建模长距离信息,但其二次方计算复杂度却使其在高分辨率图像场景中举步维艰。状态空间模型(SSMs)虽在自然语言处理中以线性复杂度实现长序列建模,但其向视觉领域迁移时面临两大棘手挑战:一是需将二维图像展平为一维序列,这会破坏图像的局部空间关联性,导致空间结构断裂;二是现有方法为弥补空间信息缺失而采用多方向扫描,却带来计算成本的激增,如 VMamba 的计算量可达单方向扫描的 4 倍。EVSS 模块则另辟蹊径,通过轻量化几何变换与单方向扫描的创新组合,巧妙突破上述瓶颈,实现了高效的非局部信息建模。
上面是原模型,下面是改进模型
1. 高效视觉状态空间模块EVSS介绍
EVSS 模块的核心思想是让状态空间模型(SSMs)更适配视觉数据的空间特性,同时避免高计算成本。传统状态空间模型处理图像时需要将二维像素 “拍扁” 成一维序列,这会破坏图像的局部结构(如相邻像素的关联性),而直接采用多方向扫描(如上下、左右、对角线等)又会大幅增加计算量。EVSS 模块的创新在于:用简单的几何变换(如翻转图像、旋转图像或转置宽高维度)替代多方向扫描。例如,在每次进入状态空间模型的扫描流程前,先对图像特征进行水平翻转或转置(交换宽和高),使单方向的扫描(如从左到右)能间接捕捉到不同方向的空间信息(如翻转后的 “从左到右” 相当于原始图像的 “从右到左”)。通过这种方式,模型无需同时进行多个方向的扫描,仅用单方向扫描结合几何变换,就能高效捕捉全局和多方向的上下文信息,同时保持低计算复杂度。
EVSS 模块由三个关键部分组成,形成一条高效的特征处理流水线:
-
几何变换层(GeoT):在处理图像特征前,根据模块的位置(索引)自动选择几何变换方式。例如:奇数索引的模块对输入特征进行水平和垂直翻转,相当于将图像 “上下左右颠倒”;偶数索引的模块对输入特征进行转置,交换宽和高维度,相当于将图像 “旋转 90 度”
-
选择性扫描模块(基于 Mamba 的 S6 机制)
-
输入处理:将变换后的图像特征通过 1×1 卷积压缩通道数,并拆分为两条分支:分支 1(全局信息分支):先通过 3×3 的深度卷积提取局部特征,再将特征 “拍扁” 成一维序列,送入状态空间模型的选择性扫描机制(S6)。S6 会递归地处理序列,重点记忆与去模糊相关的关键信息(如边缘、纹理),忽略无关内容,从而捕捉长距离依赖关系(如相隔较远的像素如何共同影响模糊程度)。分支 2(门控分支):直接对特征进行激活处理(如 GeLU 函数),生成 “门控信号”,用于调节全局信息分支的输出,确保只有有用的特征被保留。
-
特征融合:将全局信息分支的输出与门控信号相乘,再通过 1×1 卷积恢复通道数,得到融合后的特征。
-
-
频域增强前馈网络(EDFFN):在模块的最后阶段,对融合后的特征进行频域分析,自动筛选出对去模糊最重要的频率成分(如高频的细节纹理和低频的整体结构),抑制无关噪。
2. YOLOv11与高效视觉状态空间模块EVSS的结合
EVSS 模块嵌入 YOLOv11 后,借助轻量化几何变换与单方向扫描机制,强化图像全局与局部特征的交互关联,有效消除输入图像模糊对目标检测的影响,显著提升小目标和低对比度目标的检测精准度。
3. 高效视觉状态空间模块EVSS代码部分
视频讲解:
YOLOv8_improve/YOLOv11.md at master · tgf123/YOLOv8_improve · GitHub
用一篇论文教您如何使用YOLOv11改进模块写一篇1、2区论文_哔哩哔哩_bilibili
YOLOv11模型改进讲解,教您如何修改YOLOv11_哔哩哔哩_bilibili
YOLOv11全部代码,现有几十种改进机制。
4. 高效视觉状态空间模块EVSS引入到YOLOv11中
第一: 将下面的核心代码复制到D:\model\yolov11\ultralytics\change_model路径下,如下图所示。
第二:在task.py中导入包
第三:在YOLOv11\ultralytics\nn\tasks.py中的模型配置部分下面代码
第四:将模型配置文件复制到YOLOV11.YAMY文件中
第五:运行成功
from ultralytics.models import NAS, RTDETR, SAM, YOLO, FastSAM, YOLOWorld
import torch
if __name__=="__main__":
# 使用自己的YOLOv8.yamy文件搭建模型并加载预训练权重训练模型
model = YOLO("/home/shengtuo/tangfan/YOLO11/ultralytics/cfg/models/11/yolo11_EVSSM.yaml")\
# .load(r'E:\Part_time_job_orders\YOLO\YOLOv11\yolo11n.pt') # build from YAML and transfer weights
results = model.train(data="/home/shengtuo/tangfan/YOLO11/ultralytics/cfg/datasets/VOC_my.yaml",
epochs=300,
imgsz=640,
batch=32,
# cache = False,
# single_cls = False, # 是否是单类别检测
# workers = 0,
# resume=r'D:/model/yolov8/runs/detect/train/weights/last.pt',
amp = True
)