YOLOv10改进 | 特殊场景检测篇 | 单阶段盲真实图像去噪网络RIDNet辅助YOLOv10图像去噪(全网独家首发)

 一、本文介绍

本文给大家带来的改进机制是单阶段盲真实图像去噪网络RIDNet,RIDNet(Real Image Denoising with Feature Attention)是一个用于真实图像去噪的卷积神经网络(CNN),旨在解决现有去噪方法在处理真实噪声图像时性能受限的问题。通过单阶段结构和特征注意机制,RIDNet在多种数据集上展示了其优越性,下面的图片为其效果图片包括和其它图像图像网络的对比图。

欢迎大家订阅我的专栏一起学习YOLO!   

  专栏回顾:YOLOv10改进系列专栏——本专栏持续复习各种顶会内容——科研必备 


目录

 一、本文介绍

二、RIDNet 网络的原理和机制

三、核心代码 

四、手把手教你添加RIDNet 

4.1 修改一

4.2 修改二 

4.3 修改三 

4.4 修改四 

五、RIDNet 的yaml文件和运行记录

5.1 RIDNet 的yaml文件

5.2 训练代码 

5.3 RIDNet 的训练过程截图 

五、本文总结


二、RIDNet 网络的原理和机制

官方论文地址: 官方论文地址点击此处即可跳转

官方代码地址: 官方代码地址点击此处即可跳转


RIDNet(Real Image Denoising with Feature Attention)是一个用于真实图像去噪的卷积神经网络(CNN),旨在解决现有去噪方法在处理真实噪声图像时性能受限的问题。通过单阶段结构和特征注意机制,RIDNet在多种数据集上展示了其优越性。

网络架构
RIDNet由三个主要模块组成:

1. 特征提取模块(Feature Extraction Module):
   该模块包含一个卷积层,旨在从输入的噪声图像中提取初始特征。

2. 特征学习模块(Feature Learning Module):

  •    核心部分是增强注意模块(Enhanced Attention Module,EAM),使用残差在残差结构(Residual on Residual)和特征注意机制来增强特征学习能力。
  •    EAM包括两个主要部分:
  •    特征提取子模块:通过两个膨胀卷积层和一个合并卷积层提取和学习特征。
  •     特征注意子模块:使用全局平均池化和自门控机制生成特征注意力,调整每个通道的特征权重,以突出重要特征。

3. 重建模块(Reconstruction Module):
   包含一个卷积层,将学习到的特征重建为去噪后的图像。

3. 特征注意机制
特征注意机制通过以下步骤实现:
1. 全局平均池化(Global Average Pooling):
   将特征图从 `h × w × c` 缩小到 `1 × 1 × c`,捕捉全局上下文信息。
2. 自门控机制(Self-Gating Mechanism):
   使用两个卷积层和Sigmoid激活函数调整特征图的权重。
   第一个卷积层减少通道数,第二个卷积层恢复原始通道数,最终生成特征注意力。
3. 特征调整(Feature Rescaling):
   通过特征注意力调整每个通道的特征权重,增强重要特征。

跳跃连接
RIDNet使用了多种跳跃连接,以确保信息的高效流动和梯度的稳定传递:
1. 长跳跃连接(Long Skip Connection,LSC):
   连接输入和EAM模块的输出,增强信息流动。
2. 短跳跃连接(Short Skip Connection,SSC):
   连接EAM内部的不同层,确保特征图的有效传递。
3.局部连接(Local Connection,LC)**:
   在EAM内部实现局部特征学习。

结论:RIDNet在多个合成和真实噪声数据集上进行了广泛的实验,展示了其在定量指标(如PSNR)和视觉质量上的优越性。与现有最先进的算法相比,RIDNet在处理合成噪声和真实噪声图像时均表现出色。RIDNet通过引入特征注意机制和残差在残差结构,实现了对真实图像去噪的有效处理。其单阶段结构、跳跃连接和特征注意机制确保了高效的特征学习和信息传递,使其在多个数据集上均取得了优异的性能。


三、核心代码 

这个代码基础版本原先有1000+GFLOPs,我将其Block层数优化了一些,并将通道数减少了一部分将参数量降低到了20+。

import math
import torch
import torch.nn as nn
import torch.nn.functional as Fdef default_conv(in_channels, out_channels, kernel_size, bias=True):return nn.Conv2d(in_channels, out_channels, kernel_size,padding=(kernel_size//2), bias=bias)class MeanShift(nn.Conv2d):def __init__(self, rgb_range, rgb_mean, rgb_std, sign=-1):super(MeanShift, self).__init__(3, 3, kernel_size=1)std = torch.Tensor(rgb_std)self.weight.data = torch.eye(3).view(3, 3, 1, 1)self.weight.data.div_(std.view(3, 1, 1, 1))self.bias.data = sign * rgb_range * torch.Tensor(rgb_mean)self.bias.data.div_(std)self.requires_grad = Falsedef init_weights(modules):passclass Merge_Run(nn.Module):def __init__(self,in_channels, out_channels,ksize=3, stride=1, pad=1, dilation=1):super(Merge_Run, self).__init__()self.body1 = nn.Sequential(nn.Conv2d(in_channels, out_channels, ksize, stride, pad),nn.ReLU(inplace=True))self.body2 = nn.Sequential(nn.Conv2d(in_channels, out_channels, ksize, stride, 2, 2),nn.ReLU(inplace=True))self.body3 = nn.Sequential(nn.Conv2d(in_channels * 2, out_channels, ksize, stride, pad),nn.ReLU(inplace=True))init_weights(self.modules)def forward(self, x):out1 = self.body1(x)out2 = self.body2(x)c = torch.cat([out1, out2], dim=1)c_out = self.body3(c)out = c_out + xreturn outclass Merge_Run_dual(nn.Module):def __init__(self,in_channels, out_channels,ksize=3, stride=1, pad=1, dilation=1):super(Merge_Run_dual, self).__init__()self.body1 = nn.Sequential(nn.Conv2d(in_channels, out_channels, ksize, stride, pad),nn.ReLU(inplace=True),nn.Conv2d(in_channels, out_channels, ksize, stride, 2, 2),nn.ReLU(inplace=True))self.body2 = nn.Sequential(nn.Conv2d(in_channels, out_channels, ksize, stride, 3, 3),nn.ReLU(inplace=True),nn.Conv2d(in_channels, out_channels, ksize, stride, 4, 4),nn.ReLU(inplace=True))self.body3 = nn.Sequential(nn.Conv2d(in_channels * 2, out_channels, ksize, stride, pad),nn.ReLU(inplace=True))init_weights(self.modules)def forward(self, x):out1 = self.body1(x)out2 = self.body2(x)c = torch.cat([out1, out2], dim=1)c_out = self.body3(c)out = c_out + xreturn outclass BasicBlock(nn.Module):def __init__(self,in_channels, out_channels,ksize=3, stride=1, pad=1):super(BasicBlock, self).__init__()self.body = nn.Sequential(nn.Conv2d(in_channels, out_channels, ksize, stride, pad),nn.ReLU(inplace=True))init_weights(self.modules)def forward(self, x):out = self.body(x)return outclass BasicBlockSig(nn.Module):def __init__(self,in_channels, out_channels,ksize=3, stride=1, pad=1):super(BasicBlockSig, self).__init__()self.body = nn.Sequential(nn.Conv2d(in_channels, out_channels, ksize, stride, pad),nn.Sigmoid())init_weights(self.modules)def forward(self, x):out = self.body(x)return outclass ResidualBlock(nn.Module):def __init__(self,in_channels, out_channels):super(ResidualBlock, self).__init__()self.body = nn.Sequential(nn.Conv2d(in_channels, out_channels, 3, 1, 1),nn.ReLU(inplace=True),nn.Conv2d(out_channels, out_channels, 3, 1, 1),)init_weights(self.modules)def forward(self, x):out = self.body(x)out = F.relu(out + x)return outclass EResidualBlock(nn.Module):def __init__(self,in_channels, out_channels,group=1):super(EResidualBlock, self).__init__()self.body = nn.Sequential(nn.Conv2d(in_channels, out_channels, 3, 1, 1, groups=group),nn.ReLU(inplace=True),nn.Conv2d(out_channels, out_channels, 3, 1, 1, groups=group),nn.ReLU(inplace=True),nn.Conv2d(out_channels, out_channels, 1, 1, 0),)init_weights(self.modules)def forward(self, x):out = self.body(x)out = F.relu(out + x)return outclass CALayer(nn.Module):def __init__(self, channel, reduction=16):super(CALayer, self).__init__()self.avg_pool = nn.AdaptiveAvgPool2d(1)self.c1 = BasicBlock(channel, channel // reduction, 1, 1, 0)self.c2 = BasicBlockSig(channel // reduction, channel, 1, 1, 0)def forward(self, x):y = self.avg_pool(x)y1 = self.c1(y)y2 = self.c2(y1)return x * y2class Block(nn.Module):def __init__(self, in_channels, out_channels, group=1):super(Block, self).__init__()self.r1 = Merge_Run_dual(in_channels, out_channels)self.r2 = ResidualBlock(in_channels, out_channels)self.r3 = EResidualBlock(in_channels, out_channels)# self.g = ops.BasicBlock(in_channels, out_channels, 1, 1, 0)self.ca = CALayer(in_channels)def forward(self, x):r1 = self.r1(x)r2 = self.r2(r1)r3 = self.r3(r2)# g = self.g(r3)out = self.ca(r3)return outclass RIDNET(nn.Module):def __init__(self, args):super(RIDNET, self).__init__()n_feats = 16kernel_size = 3rgb_range = 255mean = (0.4488, 0.4371, 0.4040)std = (1.0, 1.0, 1.0)self.sub_mean = MeanShift(rgb_range, mean, std)self.add_mean = MeanShift(rgb_range, mean, std, 1)self.head = BasicBlock(3, n_feats, kernel_size, 1, 1)self.b1 = Block(n_feats, n_feats)self.b2 = Block(n_feats, n_feats)self.b3 = Block(n_feats, n_feats)self.b4 = Block(n_feats, n_feats)self.tail = nn.Conv2d(n_feats, 3, kernel_size, 1, 1, 1)def forward(self, x):s = self.sub_mean(x)h = self.head(s)# b1 = self.b1(h)# b2 = self.b2(b1)# b3 = self.b3(b2)b_out = self.b4(h)res = self.tail(b_out)out = self.add_mean(res)f_out = out + xreturn f_outif __name__ == "__main__":# Generating Sample imageimage_size = (1, 3, 640, 640)image = torch.rand(*image_size)# Modelmodel = RIDNET(3)out = model(image)print(out.size())


四、手把手教你添加RIDNet 

4.1 修改一

第一还是建立文件,我们找到如下ultralytics/nn文件夹下建立一个目录名字呢就是'Addmodules'文件夹(用群内的文件的话已经有了无需新建)!然后在其内部建立一个新的py文件将核心代码复制粘贴进去即可。


4.2 修改二 

第二步我们在该目录下创建一个新的py文件名字为'__init__.py'(用群内的文件的话已经有了无需新建),然后在其内部导入我们的检测头如下图所示。


4.3 修改三 

第三步我门中到如下文件'ultralytics/nn/tasks.py'进行导入和注册我们的模块(用群内的文件的话已经有了无需重新导入直接开始第四步即可)

从今天开始以后的教程就都统一成这个样子了,因为我默认大家用了我群内的文件来进行修改!!


4.4 修改四 

按照我的添加在parse_model里添加即可。

到此就修改完成了,大家可以复制下面的yaml文件运行。


五、RIDNet 的yaml文件和运行记录

5.1 RIDNet 的yaml文件

此版本训练信息:YOLOv10n-RIDNet summary: 541 layers, 2811717 parameters, 2811701 gradients, 28.2 GFLOPs

# Ultralytics YOLO 🚀, AGPL-3.0 license
# YOLOv10 object detection model. For Usage examples see https://docs.ultralytics.com/tasks/detect# Parameters
nc: 80 # number of classes
scales: # model compound scaling constants, i.e. 'model=yolov10n.yaml' will call yolov10.yaml with scale 'n'# [depth, width, max_channels]n: [0.33, 0.25, 1024]backbone:# [from, repeats, module, args]- [-1, 1, RIDNET, []] # 0-P1/2- [-1, 1, Conv, [64, 3, 2]] # 1-P1/2- [-1, 1, Conv, [128, 3, 2]] # 2-P2/4- [-1, 3, C2f, [128, True]]- [-1, 1, Conv, [256, 3, 2]] # 4-P3/8- [-1, 6, C2f, [256, True]]- [-1, 1, SCDown, [512, 3, 2]] # 6-P4/16- [-1, 6, C2f, [512, True]]- [-1, 1, SCDown, [1024, 3, 2]] # 8-P5/32- [-1, 3, C2f, [1024, True]]- [-1, 1, SPPF, [1024, 5]] # 10- [-1, 1, PSA, [1024]] # 11# YOLOv10.0n head
head:- [-1, 1, nn.Upsample, [None, 2, "nearest"]]- [[-1, 7], 1, Concat, [1]] # cat backbone P4- [-1, 3, C2f, [512]] # 14- [-1, 1, nn.Upsample, [None, 2, "nearest"]]- [[-1, 5], 1, Concat, [1]] # cat backbone P3- [-1, 3, C2f, [256]] # 17 (P3/8-small)- [-1, 1, Conv, [256, 3, 2]]- [[-1, 14], 1, Concat, [1]] # cat head P4- [-1, 3, C2f, [512]] # 20 (P4/16-medium)- [-1, 1, SCDown, [512, 3, 2]]- [[-1, 11], 1, Concat, [1]] # cat head P5- [-1, 3, C2fCIB, [1024, True, True]] # 23 (P5/32-large)- [[17, 20, 23], 1, v10Detect, [nc]] # Detect(P3, P4, P5)


5.2 训练代码 

大家可以创建一个py文件将我给的代码复制粘贴进去,配置好自己的文件路径即可运行。

import warnings
warnings.filterwarnings('ignore')
from ultralytics import YOLOif __name__ == '__main__':model = YOLO('ultralytics/cfg/models/v8/yolov8-C2f-FasterBlock.yaml')# model.load('yolov8n.pt') # loading pretrain weightsmodel.train(data=r'替换数据集yaml文件地址',# 如果大家任务是其它的'ultralytics/cfg/default.yaml'找到这里修改task可以改成detect, segment, classify, posecache=False,imgsz=640,epochs=150,single_cls=False,  # 是否是单类别检测batch=4,close_mosaic=10,workers=0,device='0',optimizer='SGD', # using SGD# resume='', # 如过想续训就设置last.pt的地址amp=False,  # 如果出现训练损失为Nan可以关闭ampproject='runs/train',name='exp',)


5.3 RIDNet 的训练过程截图 


五、本文总结

到此本文的正式分享内容就结束了,在这里给大家推荐我的YOLOv10改进有效涨点专栏,本专栏目前为新开的平均质量分98分,后期我会根据各种最新的前沿顶会进行论文复现,也会对一些老的改进机制进行补充,如果大家觉得本文帮助到你了,订阅本专栏,关注后续更多的更新~

  专栏回顾:YOLOv10改进系列专栏——本专栏持续复习各种顶会内容——科研必备 

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

c# 容器变换

List<Tuple<int, double, bool>> 变为List<Tuple<int, bool>>集合 如果您有一个List<Tuple<int, double, bool>>并且您想要将其转换为一个List<Tuple<int, bool>>集合&#xff0c;忽略double值&#xff0c;您可以使用LINQ的S…

卷积神经网络-猫狗识别实战

课程来自bilibiliMomodel平台 全长只有两个小时&#xff0c;理论部分讲得很粗糙 1 人的视觉和计算机视觉 人的大脑&#xff1a;神经元细胞&#xff0c;轴突发送信号&#xff0c;树突接收信号&#xff0c;互相连接&#xff0c;连接的强度和状态会随着新的经历刺激而变化。 用…

server nat表和会话表的作用及NAT地址转换详细

本章节主要讲nat技术的基础 -会话表的建立也是看5元组 -状态检测技术的回包一样也看5元组&#xff0c;但是状态检测技术会看的除开5元组还有更多东西 老哥&#xff0c;你真的应该好好注意一个东西&#xff1a;我们的会话表只是为了后续包的转发&#xff0c;会话表是记录的首…

【机器学习】和【人工智能】在航空航天中的应用

作者主页: 知孤云出岫 目录 引言机器学习和人工智能在航空航天中的应用1. 预测性维护2. 飞行路径优化3. 自动驾驶飞行器 未来展望1. 增强人机协作2. 更智能的空中交通管理3. 高效的航空制造 结论参考文献 引言 随着科技的迅猛发展&#xff0c;机器学习和人工智能&#xff08;…

【python报错已解决】 “Invalid Array Index“

&#x1f3ac; 鸽芷咕&#xff1a;个人主页 &#x1f525; 个人专栏: 《C干货基地》《粉丝福利》 ⛺️生活的理想&#xff0c;就是为了理想的生活! 文章目录 引言一、问题描述1.1 报错示例1.2 报错分析1.3 解决思路 二、解决方法&#xff1a;2.1 方法一&#xff1a;检查索引范…

win32:第一个窗口程序-应用程序入口点(part.6)

第一个窗口程序的最后一部分&#xff1a;应用程序入口函数wWinMain&#xff1b;这是Windows应用程序的主函数&#xff0c;负责初始化应用程序、注册窗口类、创建主窗口并进入消息循环处理消息。 int APIENTRY wWinMain(_In_ HINSTANCE hInstance,_In_opt_ HINSTANCE hPrevInst…

pytorch说明

深度学习中的重要概念&#xff1a; 激活函数&#xff1a; 激活函数的必要性&#xff1a;激活函数不是绝对必须的&#xff0c;但在深度学习中&#xff0c;它们几乎总是被使用。激活函数可以引入非线性&#xff0c;这使得神经网络能够学习更复杂的模式。 激活函数的位置&#x…

用HTML和CSS实现提示工具(tooltip)及HTML元素的定位

所谓提示工具&#xff0c;是指将鼠标移动到某个HTML元素&#xff08;工具&#xff09;时会显示一些提示内容&#xff08;提示文本&#xff09;&#xff0c;而鼠标移出工具元素的范围时提示文本就消失了。考虑到提示文本元素应当在鼠标进入工具元素时显示&#xff0c;鼠标离开工…

Mac安装stable diffusion 工具

文章目录 1.安装 Homebrew2.安装 stable diffusion webui 的依赖3.下载 stable diffusion webui 代码4.启动 stable diffusion webui 本体5.下载模型6.这里可能会遇到一个clip-vit-large-patch14报错 参考&#xff1a;https://brew.idayer.com/install/stable-diffusion-webui/…

STM32入门开发操作记录(二)——LED与蜂鸣器

目录 一、工程模板二、点亮主板1. 配置寄存器2. 调用库函数 三、LED1. 闪烁2. 流水灯 四、蜂鸣器 一、工程模板 参照第一篇&#xff0c;新建工程目录ProjectMould&#xff0c;将先前打包好的Start&#xff0c;Library和User文件^C^V过来&#xff0c;并在Keil5内完成器件支持包的…

jenkins系列-01.docker安装jenkins

进入官网&#xff1a;https://www.jenkins.io/ 使用LONG term support版本&#xff1a;2.387.1 docker pull jenkins/jenkins:2.387.1-lts 拉取镜像&#xff1a; 编写docker-compose文件&#xff1a; 启动jenkins: 查看启动日志&#xff1a; 默认生成的密码&#xff1a;…

基于springboot+vue+uniapp的超市购物系统小程序

开发语言&#xff1a;Java框架&#xff1a;springbootuniappJDK版本&#xff1a;JDK1.8服务器&#xff1a;tomcat7数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09;数据库工具&#xff1a;Navicat11开发软件&#xff1a;eclipse/myeclipse/ideaMaven包&#…

LeetCode 142.环形链表2 C写法

LeetCOde 142.环形链表2 C写法 思路1&#x1f914;&#xff1a; ​ 用环形链表的方法&#xff0c;快慢指针找到slow和fast的相遇点&#xff0c;此时头到入口点的位置与相遇点到入口点的距离一样。 ​ 我们假设头到入口点的长度为L&#xff0c;环的长度为C&#xff0c;相遇点到入…

Rust 测试的组织结构

测试的组织结构 本章一开始就提到&#xff0c;测试是一个复杂的概念&#xff0c;而且不同的开发者也采用不同的技术和组织。Rust 社区倾向于根据测试的两个主要分类来考虑问题&#xff1a;单元测试&#xff08;unit tests&#xff09;与 集成测试&#xff08;integration test…

负荷预测 | Matlab基于Transformer-LSTM多变量时间序列多步预测

目录 效果一览基本介绍程序设计参考资料 效果一览 基本介绍 1.Matlab基于Transformer-LSTM多变量时间序列多步预测&#xff1b; 2.多变量时间序列数据集&#xff08;负荷数据集&#xff09;&#xff0c;采用前96*2个时刻预测的特征和负荷数据预测未来96个时刻的负荷数据&#x…

记一次饱经挫折的阿里云ROS部署经历

前言 最近在参加的几个项目测评里&#xff0c;我发现**“一键部署”这功能真心好用&#xff0c;省下了不少宝贵时间和力气&#xff0c;再加上看到阿里云现在有个开源上云**的活动。趁着这波热潮&#xff0c;今天就聊聊怎么从头开始&#xff0c;一步步搞定阿里云的资源编排服务…

【持续集成_06课_Jenkins高级pipeline应用】

一、创建项目选择pipeline的风格 它主要是以脚本&#xff08;它自己的语言&#xff09;的方式进行运行&#xff0c;一般由运维去做的事情&#xff0c;作为测试而言。了解即可。 --- 体现形式全部通过脚本去实现&#xff1a;执行之前&#xff08;拉取代码&#xff09;执行&…

Linux:Linux网络总结(附下载链接)

文章目录 下载链接网络问题综合问题访问一个网页的全过程&#xff1f;WebSocket HTTPHTTP基本概念GET与POSTHTTP特性HTTP缓存技术HTTP的演变HTTP1.1 优化 HTTPSHTTP与HTTPS有哪些区别&#xff1f;HTTPS解决了HTTP的哪些问题&#xff1f;HTTPS如何解决的&#xff1f;HTTPS是如何…

# Redis 入门到精通(二)通用指令

Redis 入门到精通&#xff08;二&#xff09;通用指令 一、redis 通用指令-key 基本操作 1、key 特征 key是一个字符串&#xff0c;通过key获取redis中保存的数据。 2、key 应该设计哪些操作? 对于 key 自身状态的相关操作&#xff0c;例如:删除&#xff0c;判定存在&…

企业网络实验(vmware虚拟机充当DHCP服务器)所有IP全部保留,只为已知mac分配固定IP

文章目录 需求实验修改dhcp虚拟机配置文件测试PC获取IP查看user-bind 需求 (vmware虚拟机充当DHCP服务器)所有IP全部保留&#xff0c;只为已知mac分配固定IP 实验 前期配置&#xff1a; https://blog.csdn.net/xzzteach/article/details/140406092 后续配置均在以上配置的前…