当前位置: 首页 > news >正文

【YOLOv8改进[Backbone]】使用SCINet改进YOLOv8在黑暗环境的目标检测效果

目录

一 SCINet

1 本文方法

① 权重共享的照明学习

② 自校准模块

③ 无监督训练损失

 二 使用SCINet助力YOLOv8在黑暗环境的目标检测效果

1 整体修改

2 配置文件

3 训练

其他


一 SCINet

官方论文地址:https://arxiv.org/pdf/2204.10137

官方代码地址:GitCode - 开发者的代码家园

现有的弱光图像增强技术不仅难以处理视觉质量和计算效率问题,而且在未知的复杂场景下通常无效。在本文中,提出了一种新的自校准照明(SCI)学习框架,用于在现实世界低光场景下快速,灵活和鲁棒的增亮图像。具体来说,建立了一个具有权重共享的级联照明学习过程来处理这个任务。作者考虑到级联模式的计算负担,构建了自校准模块,实现了各阶段结果之间的收敛,产生了仅使用单个基本块进行推理的增益(但在以往的工作中尚未被利用),大大降低了计算成本。然后,定义了无监督训练损失,以提高模型适应一般场景的能力。进一步,进行了全面的探索,挖掘SCI的固有属性(现有作品所缺乏的),包括操作不敏感的适应性。最后,大量的实验和消融研究充分表明了这一方法在质量和效率上的优势。在微光人脸检测和夜间语义分割等方面的应用充分显示了该方法潜在的实用价值。

在本文中,成功地建立了一个轻量级而有效的框架,即自校准照明(SCI)用于针对不同现实场景的低光图像增强。不仅对SCI的优良特性进行了深入的探索,还进行了大量的实验,证明了在弱光图像增强、暗人脸检测、夜间语义分割等方面的有效性和优越性

1 本文方法

① 权重共享的照明学习

建立了一个具有权重共享级联照明学习过程来处理低照度图像增强的任务。各个阶段共享权重。

② 自校准模块

构建了自校准模块,减少计算负担,实现了各阶段结果之间的收敛,产生了仅使用单个基本块进行推理的增益。

③ 无监督训练损失

定义了无监督训练损失,以提高模型适应一般场景的能力。

下图为SCI的整个框架。在训练阶段,SCI由照度估计和自校准模块组成。将自校准的模块映射添加到原始低照度输入中,作为下一阶段照度估计的输入。注意,这两个模块在整个训练过程中分别是共享参数。在测试阶段,只使用单个照明估计模块。权重共享的照明学习和自校准模块的设计为减少计算量并且提升结果的稳定性。

下图为比较是否使用自校准模块时各阶段结果的t-SNE[21]分布。这说明了为什么可以使用单级进行测试,即SCI中每级的结果都可以快速收敛到相同的值,而w/o自校准模块却无法始终实现这一点。

以下为各方法对比结果

 二 使用SCINet助力YOLOv8在黑暗环境的目标检测效果

整个结构的示意图如下所示:

1 整体修改

① 添加SCINet.py文件

ultralytics/nn/modules目录下新建SCINet.py文件,文件的内容如下:

import torch
import torch.nn as nn__all__ = ['EnhanceNetwork']class EnhanceNetwork(nn.Module):def __init__(self, layers, channels):super(EnhanceNetwork, self).__init__()kernel_size = 3dilation = 1padding = int((kernel_size - 1) / 2) * dilationself.in_conv = nn.Sequential(nn.Conv2d(in_channels=3, out_channels=channels, kernel_size=kernel_size, stride=1, padding=padding),nn.ReLU())self.conv = nn.Sequential(nn.Conv2d(in_channels=channels, out_channels=channels, kernel_size=kernel_size, stride=1, padding=padding),nn.BatchNorm2d(channels),nn.ReLU())self.blocks = nn.ModuleList()for i in range(layers):self.blocks.append(self.conv)self.out_conv = nn.Sequential(nn.Conv2d(in_channels=channels, out_channels=3, kernel_size=3, stride=1, padding=1),nn.Sigmoid())def forward(self, input):fea = self.in_conv(input)for conv in self.blocks:fea = fea + conv(fea)fea = self.out_conv(fea)illu = fea + inputillu = torch.clamp(illu, 0.0001, 1)return illuclass CalibrateNetwork(nn.Module):def __init__(self, layers, channels):super(CalibrateNetwork, self).__init__()kernel_size = 3dilation = 1padding = int((kernel_size - 1) / 2) * dilationself.layers = layersself.in_conv = nn.Sequential(nn.Conv2d(in_channels=3, out_channels=channels, kernel_size=kernel_size, stride=1, padding=padding),nn.BatchNorm2d(channels),nn.ReLU())self.convs = nn.Sequential(nn.Conv2d(in_channels=channels, out_channels=channels, kernel_size=kernel_size, stride=1, padding=padding),nn.BatchNorm2d(channels),nn.ReLU(),nn.Conv2d(in_channels=channels, out_channels=channels, kernel_size=kernel_size, stride=1, padding=padding),nn.BatchNorm2d(channels),nn.ReLU())self.blocks = nn.ModuleList()for i in range(layers):self.blocks.append(self.convs)self.out_conv = nn.Sequential(nn.Conv2d(in_channels=channels, out_channels=3, kernel_size=3, stride=1, padding=1),nn.Sigmoid())def forward(self, input):fea = self.in_conv(input)for conv in self.blocks:fea = fea + conv(fea)fea = self.out_conv(fea)delta = input - feareturn deltaclass Network(nn.Module):def __init__(self, stage=3):super(Network, self).__init__()self.stage = stageself.enhance = EnhanceNetwork(layers=1, channels=3)self.calibrate = CalibrateNetwork(layers=3, channels=16)self._criterion = LossFunction()def weights_init(self, m):if isinstance(m, nn.Conv2d):m.weight.data.normal_(0, 0.02)m.bias.data.zero_()if isinstance(m, nn.BatchNorm2d):m.weight.data.normal_(1., 0.02)def forward(self, input):ilist, rlist, inlist, attlist = [], [], [], []input_op = inputfor i in range(self.stage):inlist.append(input_op)i = self.enhance(input_op)r = input / ir = torch.clamp(r, 0, 1)att = self.calibrate(r)input_op = input + attilist.append(i)rlist.append(r)attlist.append(torch.abs(att))return ilist, rlist, inlist, attlistdef _loss(self, input):i_list, en_list, in_list, _ = self(input)loss = 0for i in range(self.stage):loss += self._criterion(in_list[i], i_list[i])return lossclass Finetunemodel(nn.Module):def __init__(self, weights):super(Finetunemodel, self).__init__()self.enhance = EnhanceNetwork(layers=1, channels=3)self._criterion = LossFunction()base_weights = torch.load(weights)pretrained_dict = base_weightsmodel_dict = self.state_dict()pretrained_dict = {k: v for k, v in pretrained_dict.items() if k in model_dict}model_dict.update(pretrained_dict)self.load_state_dict(model_dict)def weights_init(self, m):if isinstance(m, nn.Conv2d):m.weight.data.normal_(0, 0.02)m.bias.data.zero_()if isinstance(m, nn.BatchNorm2d):m.weight.data.normal_(1., 0.02)def forward(self, input):i = self.enhance(input)r = input / ir = torch.clamp(r, 0, 1)return i, rdef _loss(self, input):i, r = self(input)loss = self._criterion(input, i)return loss

② 修改ultralytics/nn/tasks.py文件

具体的修改内容如下图所示:

修改parse_model函数的内容如下所示:

2 配置文件

yolov8_SCINet.yaml 的内容与原版对比:

3 训练

上述修改完毕后,开始训练吧!🌺🌺🌺🌺🌺🌺

训练示例:

yolo task=detect mode=train model=cfg/models/v8/yolov8_SCINet.yaml data=cfg/datasets/coco128.yaml epochs=200 batch=16 device=cpu project=yolov8

其他

说明:私信问题,不回答了哈,有问题可以评论,会随缘回答哈。希望理解哈!💛 💙 💜 ❤️ 💚 💛 💙 💜 ❤️ 💚 

到此,本文分享的内容就结束啦!遇见便是缘,感恩遇见!!!💛 💙 💜 ❤️ 💚 

http://www.lryc.cn/news/347957.html

相关文章:

  • ASE docker related research
  • maven .lastUpdated文件作用
  • gtest的编译与使用
  • 【 npm详解:从入门到精通】
  • 【Web后端】实现文件上传
  • react 逻辑 AND 运算符 ()
  • Redis详解(二)
  • 嵌入式:基于STM32的智能家居照明控制系统
  • 三种基本排序-冒泡,选择,二分
  • windows查找重复的物理地址
  • linux进阶高级配置,你需要知道的有哪些(8)-shell脚本应用(三)
  • 安全测试|常见SQL注入攻击方式、影响及预防
  • 【Git】Git在Gitee上的基本操作指南
  • 国债期货怎么买?十年国债交易手册
  • 公司申请增加公众号数量
  • 什么是.faust勒索病毒?应该如何防御?
  • 邓闲小——生存、生活、生命|真北写作
  • 品牌舆情都包含什么内容?建议收藏
  • MQTT 5.0 报文解析 04:PINGREQ 与 PINGRESP
  • 【算法刨析】完全背包
  • notepad++
  • Python ValueError: bad transparency mask
  • Linux本地部署Nightingale夜莺监控并实现远程访问提高运维效率
  • 开关电源功率测试方法:输入、输出功率测试步骤
  • QT 文字转语言插件
  • Kubernetes(k8s)的认证(Authentication)策略解析
  • Scikit-Learn决策树
  • Python面试题【python基础部分1-50】
  • 鸿蒙内核源码分析(Shell编辑篇) | 两个任务,三个阶段
  • 第Ⅷ章-Ⅱ 组合式API使用