💡💡💡本文独家改进:高层筛选特征金字塔网络(HS-FPN),能够刷选出大小目标,增强模型表达不同尺度特征的能力,助力小目标检测
💡💡💡在BCCD医学数据集实现暴力涨点。
收录
YOLOv8原创自研
💡💡💡全网独家首发创新(原创),适合paper !!!
💡💡💡 2024年计算机视觉顶会创新点适用于Yolov5、Yolov7、Yolov8等各个Yolo系列,专栏文章提供每一步步骤和源码,轻松带你上手魔改网络 !!!
💡💡💡重点:通过本专栏的阅读,后续你也可以设计魔改网络,在网络不同位置(Backbone、head、detect、loss等)进行魔改,实现创新!!!
1.MFDS-DETR原理介绍

论文: https://arxiv.org/pdf/2401.00926.pdf
摘要:在标准的医院血液检测中,传统的过程需要医生手动分离白细胞。用显微镜观察病人血液的显微图像。然后将这些分离的白细胞通过自动白细胞分类器进行分类,以确定不同的比例和体积血液样本中存在的白细胞类型,有助于疾病诊断。这种方法不是但由于以下因素,它也有很高的出错倾向作为图像质量和环境条件,这可能潜在地导致不正确的后续分类与误诊。当代白细胞检测方法表现出局限性。在处理具有较少白细胞特征的图像和不同尺度之间的差异时白细胞,在大多数情况下导致不满意的结果。为了解决这些问题,本文提出了一种创新的白细胞检测方法:多层次特征融合与变形。自我注意力检测(MFDS-DETR)。为了解决白细胞规模差异的问题,我们设计了高级筛选特征融合金字塔(HS-FPN),实现多级融合。这个模型使用高级特征作为权重以经由信道关注模块过滤低级特征信息,以及然后将筛选后的信息与高级特征合并,从而增强模型的特征表达能力。此外,我们通过合并A来解决白细胞特征缺乏的问题。在编码器中使用多尺度可变形自注意模块,在解码器中使用自注意和交叉可变形注意机制,有助于全局特征的提取。白细胞特征图。通过与其他前沿白细胞检测模型的比较,证实了所提出的MFDSDETR方法的有效性、优越性和可推广性使用私有WBCDD、公共LISC和BCCD数据集。
该架构名为MFDS-DETR(多级特征融合与可变形自注意力DETR),旨在解决检测尺度不同且在图像中可能特征有限的白细胞的挑战。
以下是MFDS-DETR架构四个部分的分解:
骨干网:这是从输入图像中提取特征的基础网络。通常,像ResNet或VGG这样的预训练卷积神经网络(CNN)被用作骨干网。
高层筛选特征金字塔网络(HS-FPN):这个组件旨在处理不同白细胞之间的尺度差异问题。它很可能是一个特征金字塔网络(FPN),创建了一个多尺度特征层次结构,允许模型检测不同大小的白细胞。高层特征用于筛选(或权衡)低层特征,然后与高层特征融合,以增强模型表达不同尺度特征的能力。
编码器:编码器负责对骨干网和HS-FPN提取的特征进行编码。它可能结合多尺度可变形自注意力模块,以进一步增强特征提取过程。可变形卷积网络可以自适应地调整其感受野,以关注图像中更多信息丰富的区域,这对于检测形状和大小变化的对象特别有用。
解码器:解码器获取编码后的特征,并使用它们来预测图像中白细胞的位置和类别。它可能使用自注意力和交叉可变形注意力机制,通过考虑特征图中的全局上下文来细化检测。

HS-FPN的结构如图2所示,包括两个主要组成部分:
- 特征选择模块;
- 特征融合模块。

为了解决白细胞数据集固有的多尺度挑战,我们开发了基于层次尺度的特征金字塔网络(HS-FPN)来完成多尺度特征融合。这使得该模型能够捕获更全面的白细胞特征信息。HS-FPN的结构如图2所示。HS-FPN主要由两个部分组成:(1)特征选择模块。(2)特征融合模块。最初,不同尺度的特征图在特征选择模块中经过筛选过程。随后,通过选择性特征融合(Selective feature Fusion, SFF)机制,将这些特征映射中的高层和低层信息协同集成。这种融合产生的特征具有丰富的语义内容,这有助于检测白细胞显微图像中的细微特征,从而增强模型的检测能力。进一步阐述这种SFF机制及其对模型性能的影响将在随后的烧蚀研究部分提供。
2.如何将HS-FPN将入到YOLOv8
2.1 新建ultralytics/nn/fpn/HSFPN.py
import torch
import torch.nn as nn
class ChannelAttention_HSFPN(nn.Module):
def __init__(self, in_planes, ratio = 4, flag=True):
super(ChannelAttention_HSFPN, self).__init__()
self.avg_pool = nn.AdaptiveAvgPool2d(1)
self.max_pool = nn.AdaptiveMaxPool2d(1)
self.conv1 = nn.Conv2d(in_planes, in_planes // ratio, 1, bias=False)
self.relu = nn.ReLU()
self.conv2 = nn.Conv2d(in_planes // ratio, in_planes, 1, bias=False)
self.flag = flag
self.sigmoid = nn.Sigmoid()
nn.init.xavier_uniform_(self.conv1.weight)
nn.init.xavier_uniform_(self.conv2.weight)
def forward(self, x):
avg_out = self.conv2(self.relu(self.conv1(self.avg_pool(x))))
max_out = self.conv2(self.relu(self.conv1(self.max_pool(x))))
out = avg_out + max_out
return self.sigmoid(out) * x if self.flag else self.sigmoid(out)
class Multiply(nn.Module):
def __init__(self) -> None:
super().__init__()
def forward(self, x):
return x[0] * x[1]
class Add(nn.Module):
def __init__(self):
super().__init__()
def forward(self, x):
return torch.sum(torch.stack(x, dim=0), dim=0)2.2 修改 tasks.py
1)首先进行注册
from ultralytics.nn.fpn.HSFPN import ChannelAttention_HSFPN , Multiply,Add2)修改 def parse_model(d, ch, verbose=True): # model_dict, input_channels(3)
nn.Conv2d将入以下代码中
if m in (Classify, Conv, ConvTranspose, GhostConv, Bottleneck, GhostBottleneck, SPP, SPPF, DWConv, Focus,
BottleneckCSP, C1, C2, C2f, C3, C3TR, C3Ghost, nn.ConvTranspose2d, DWConvTranspose2d, C3x, RepC3,nn.Conv2d):
c1, c2 = ch[f], args[0]
if c2 != nc: # if c2 not equal to number of classes (i.e. for Classify() output)
c2 = make_divisible(min(c2, max_channels) * width, 8)
args = [c1, c2, *args[1:]]
if m in (BottleneckCSP, C1, C2, C2f, C3, C3TR, C3Ghost, C3x, RepC3):
args.insert(2, n) # number of repeats
n = 1ChannelAttention_HSFPN , Multiply加入以下代码
elif m is nn.BatchNorm2d:
args = [ch[f]]
######## HSFPN #############
elif m is ChannelAttention_HSFPN:
c2 = ch[f]
args = [c2, *args]
elif m is Multiply:
c2 = ch[f[0]]
elif m is Add:
c2 = ch[f[-1]]
######## HSFPN #############2.3 yolov8_HSFPN.yaml
# Ultralytics YOLO 🚀, AGPL-3.0 license
# YOLOv8 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=yolov8n.yaml' will call yolov8.yaml with scale 'n'
# [depth, width, max_channels]
n: [0.33, 0.25, 1024] # YOLOv8n summary: 225 layers, 3157200 parameters, 3157184 gradients, 8.9 GFLOPs
s: [0.33, 0.50, 1024] # YOLOv8s summary: 225 layers, 11166560 parameters, 11166544 gradients, 28.8 GFLOPs
m: [0.67, 0.75, 768] # YOLOv8m summary: 295 layers, 25902640 parameters, 25902624 gradients, 79.3 GFLOPs
l: [1.00, 1.00, 512] # YOLOv8l summary: 365 layers, 43691520 parameters, 43691504 gradients, 165.7 GFLOPs
x: [1.00, 1.25, 512] # YOLOv8x summary: 365 layers, 68229648 parameters, 68229632 gradients, 258.5 GFLOPs
# YOLOv8.0n backbone
backbone:
# [from, repeats, module, args]
- [-1, 1, Conv, [64, 3, 2]] # 0-P1/2
- [-1, 1, Conv, [128, 3, 2]] # 1-P2/4
- [-1, 3, C2f, [128, True]]
- [-1, 1, Conv, [256, 3, 2]] # 3-P3/8
- [-1, 6, C2f, [256, True]]
- [-1, 1, Conv, [512, 3, 2]] # 5-P4/16
- [-1, 6, C2f, [512, True]]
- [-1, 1, Conv, [1024, 3, 2]] # 7-P5/32
- [-1, 3, C2f, [1024, True]]
- [-1, 1, SPPF, [1024, 5]] # 9
# YOLOv8.0n head
head:
- [-1, 1, ChannelAttention_HSFPN, [4]] # 10
- [-1, 1, nn.Conv2d, [256, 1]] # 11
- [-1, 1, nn.ConvTranspose2d, [256, 3, 2, 1, 1]] # 12
- [6, 1, ChannelAttention_HSFPN, [4]] # 13
- [-1, 1, nn.Conv2d, [256, 1]] # 14
- [12, 1, ChannelAttention_HSFPN, [4, False]] # 15
- [[-1, -2], 1, Multiply, []] # 16
- [[-1, 12], 1, Add, []] # 17
- [-1, 3, C2f, [256]] # 18 P4/16
- [12, 1, nn.ConvTranspose2d, [256, 3, 2, 1, 1]] # 19
- [4, 1, ChannelAttention_HSFPN, [4]] # 20
- [-1, 1, nn.Conv2d, [256, 1]] # 21
- [19, 1, ChannelAttention_HSFPN, [4, False]] # 22
- [[-1, -2], 1, Multiply, []] # 23
- [[-1, 19], 1, Add, []] # 24
- [-1, 3, C2f, [256]] # 25 P3/16
- [[25, 18, 11], 1, Detect, [nc]] # Detect(P3, P4, P5)