yolov26改进 | 图像复原篇 | 单阶段盲真实图像去噪网络RIDNet辅助YOLOv26图像去噪(全网独家首发) 开始讲解之前推荐一下我的专栏本专栏的内容支持(分类、检测、分割、追踪、关键点检测),专栏目前为限时折扣欢迎大家订阅本专栏本专栏每周更新5-7篇最新机制更有包含我所有改进的文件和交流群提供给大家本人定期在群内分享发表论文方法和经验。一、本文介绍本文在 YOLOv26 中加入 RIDNet主要目的就是让模型在检测前先把图片“处理干净”。实际场景中的图片经常会受到光照不足、设备噪声、背景杂乱、压缩失真等影响直接送入 YOLOv26 可能会让一些目标边缘变模糊尤其是小目标和细节不明显的目标更容易被漏检。RIDNet 可以在前端先对图像进行去噪和细节增强把无用噪声压下去同时尽量保留目标的轮廓、纹理和边缘信息这样后面的 YOLOv26 在提取特征时拿到的就是更清晰、更稳定的图像信息。简单来说这个改进相当于在检测前给图像做了一次“清洗和增强”让模型在复杂环境下看得更清楚、判断更准确从而提升整体检测效果和抗干扰能力。欢迎大家订阅我的专栏一起学习YOLO专栏链接YOLOv26有效涨点专栏包含Conv、注意力机制、主干/Backbone、损失函数、优化器、后处理等改进机制目录一、本文介绍二、RIDNet 网络的原理和机制三、核心代码四、手把手教你添加RIDNet4.1 修改一4.2 修改二4.3 修改三4.4 修改四五、RIDNet 的yaml文件和运行记录5.1 RIDNet 的yaml文件5.2 训练代码5.3 RIDNet 的训练过程截图五、本文总结二、RIDNet 网络的原理和机制​官方论文地址官方论文地址点击此处即可跳转官方代码地址官方代码地址点击此处即可跳转​RIDNetReal Image Denoising with Feature Attention是一个用于真实图像去噪的卷积神经网络CNN旨在解决现有去噪方法在处理真实噪声图像时性能受限的问题。通过单阶段结构和特征注意机制RIDNet在多种数据集上展示了其优越性。RIDNet由三个主要模块组成1. 特征提取模块Feature Extraction Module该模块包含一个卷积层旨在从输入的噪声图像中提取初始特征。2. 特征学习模块Feature Learning Module核心部分是增强注意模块Enhanced Attention ModuleEAM使用残差在残差结构Residual on Residual和特征注意机制来增强特征学习能力。EAM包括两个主要部分1特征提取子模块通过两个膨胀卷积层和一个合并卷积层提取和学习特征。2特征注意子模块使用全局平均池化和自门控机制生成特征注意力调整每个通道的特征权重以突出重要特征。3. 重建模块Reconstruction Module包含一个卷积层将学习到的特征重建为去噪后的图像。结论:RIDNet在多个合成和真实噪声数据集上进行了广泛的实验展示了其在定量指标如PSNR和视觉质量上的优越性。与现有最先进的算法相比RIDNet在处理合成噪声和真实噪声图像时均表现出色。RIDNet通过引入特征注意机制和残差在残差结构实现了对真实图像去噪的有效处理。其单阶段结构、跳跃连接和特征注意机制确保了高效的特征学习和信息传递使其在多个数据集上均取得了优异的性能。三、核心代码核心代码使用方式看章节四import torch import torch.nn as nn import torch.nn.functional as F __all__ [RIDNET] def default_conv(in_channels, out_channels, kernel_size, biasTrue): return nn.Conv2d( in_channels, out_channels, kernel_size, padding(kernel_size//2), biasbias) class MeanShift(nn.Conv2d): def __init__(self, rgb_range, rgb_mean, rgb_std, sign-1): super(MeanShift, self).__init__(3, 3, kernel_size1) 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) for p in self.parameters(): p.requires_grad False def init_weights(modules): pass class Merge_Run(nn.Module): def __init__(self, in_channels, out_channels, ksize3, stride1, pad1, dilation1): super(Merge_Run, self).__init__() self.body1 nn.Sequential( nn.Conv2d(in_channels, out_channels, ksize, stride, pad), nn.ReLU(inplaceTrue) ) self.body2 nn.Sequential( nn.Conv2d(in_channels, out_channels, ksize, stride, 2, 2), nn.ReLU(inplaceTrue) ) self.body3 nn.Sequential( nn.Conv2d(in_channels * 2, out_channels, ksize, stride, pad), nn.ReLU(inplaceTrue) ) init_weights(self.modules) def forward(self, x): out1 self.body1(x) out2 self.body2(x) c torch.cat([out1, out2], dim1) c_out self.body3(c) out c_out x return out class Merge_Run_dual(nn.Module): def __init__(self, in_channels, out_channels, ksize3, stride1, pad1, dilation1): super(Merge_Run_dual, self).__init__() self.body1 nn.Sequential( nn.Conv2d(in_channels, out_channels, ksize, stride, pad), nn.ReLU(inplaceTrue), nn.Conv2d(in_channels, out_channels, ksize, stride, 2, 2), nn.ReLU(inplaceTrue) ) self.body2 nn.Sequential( nn.Conv2d(in_channels, out_channels, ksize, stride, 3, 3), nn.ReLU(inplaceTrue), nn.Conv2d(in_channels, out_channels, ksize, stride, 4, 4), nn.ReLU(inplaceTrue) ) self.body3 nn.Sequential( nn.Conv2d(in_channels * 2, out_channels, ksize, stride, pad), nn.ReLU(inplaceTrue) ) init_weights(self.modules) def forward(self, x): out1 self.body1(x) out2 self.body2(x) c torch.cat([out1, out2], dim1) c_out self.body3(c) out c_out x return out class BasicBlock(nn.Module): def __init__(self, in_channels, out_channels, ksize3, stride1, pad1): super(BasicBlock, self).__init__() self.body nn.Sequential( nn.Conv2d(in_channels, out_channels, ksize, stride, pad), nn.ReLU(inplaceTrue) ) init_weights(self.modules) def forward(self, x): out self.body(x) return out class BasicBlockSig(nn.Module): def __init__(self, in_channels, out_channels, ksize3, stride1, pad1): 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 out class 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(inplaceTrue), 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 out class EResidualBlock(nn.Module): def __init__(self, in_channels, out_channels, group1): super(EResidualBlock, self).__init__() self.body nn.Sequential( nn.Conv2d(in_channels, out_channels, 3, 1, 1, groupsgroup), nn.ReLU(inplaceTrue), nn.Conv2d(out_channels, out_channels, 3, 1, 1, groupsgroup), nn.ReLU(inplaceTrue), 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 out class CALayer(nn.Module): def __init__(self, channel, reduction16): 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 * y2 class Block(nn.Module): def __init__(self, in_channels, out_channels, group1): 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 out class RIDNET(nn.Module): def __init__(self, args): super(RIDNET, self).__init__() n_feats 16 kernel_size 3 rgb_range 255 mean (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.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) b_out self.b4(h) res self.tail(b_out) out self.add_mean(res) f_out out x return f_out if __name__ __main__: # Generating Sample image image_size (1, 3, 640, 640) image torch.rand(*image_size) # Model model RIDNET(3) out model(image) print(out.size())四、手把手教你添加RIDNet4.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文件此版本训练信息YOLO26-RIDNet summary: 288 layers, 2,530,552 parameters, 2,530,528 gradients, 25.6 GFLOPs# Ultralytics AGPL-3.0 License - https://ultralytics.com/license # Ultralytics YOLO26 object detection model with P3/8 - P5/32 outputs # Model docs: https://docs.ultralytics.com/models/yolo26 # Task docs: https://docs.ultralytics.com/tasks/detect # Parameters nc: 80 # number of classes end2end: True # whether to use end-to-end mode reg_max: 1 # DFL bins scales: # model compound scaling constants, i.e. modelyolo26n.yaml will call yolo26.yaml with scale n # [depth, width, max_channels] n: [0.50, 0.25, 1024] # summary: 260 layers, 2,572,280 parameters, 2,572,280 gradients, 6.1 GFLOPs s: [0.50, 0.50, 1024] # summary: 260 layers, 10,009,784 parameters, 10,009,784 gradients, 22.8 GFLOPs m: [0.50, 1.00, 512] # summary: 280 layers, 21,896,248 parameters, 21,896,248 gradients, 75.4 GFLOPs l: [1.00, 1.00, 512] # summary: 392 layers, 26,299,704 parameters, 26,299,704 gradients, 93.8 GFLOPs x: [1.00, 1.50, 512] # summary: 392 layers, 58,993,368 parameters, 58,993,368 gradients, 209.5 GFLOPs # YOLO26n backbone 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, 2, C3k2, [256, False, 0.25]] - [-1, 1, Conv, [256, 3, 2]] # 4-P3/8 - [-1, 2, C3k2, [512, False, 0.25]] - [-1, 1, Conv, [512, 3, 2]] # 6-P4/16 - [-1, 2, C3k2, [512, True]] - [-1, 1, Conv, [1024, 3, 2]] # 8-P5/32 - [-1, 2, C3k2, [1024, True]] - [-1, 1, SPPF, [1024, 5, 3, True]] # 10 - [-1, 2, C2PSA, [1024]] # 11 # YOLO26n head head: - [-1, 1, nn.Upsample, [None, 2, nearest]] - [[-1, 7], 1, Concat, [1]] # cat backbone P4 - [-1, 2, C3k2, [512, True]] # 14 - [-1, 1, nn.Upsample, [None, 2, nearest]] - [[-1, 5], 1, Concat, [1]] # cat backbone P3 - [-1, 2, C3k2, [256, True]] # 17 (P3/8-small) - [-1, 1, Conv, [256, 3, 2]] - [[-1, 14], 1, Concat, [1]] # cat head P4 - [-1, 2, C3k2, [512, True]] # 20 (P4/16-medium) - [-1, 1, Conv, [512, 3, 2]] - [[-1, 11], 1, Concat, [1]] # cat head P5 - [-1, 1, C3k2, [1024, True, 0.5, True]] # 23 (P5/32-large) - [[17, 20, 23], 1, Detect, [nc]] # Detect(P3, P4, P5)5.2 训练代码大家可以创建一个py文件将我给的代码复制粘贴进去配置好自己的文件路径即可运行。import warnings warnings.filterwarnings(ignore) from ultralytics import YOLO if __name__ __main__: model YOLO(ultralytics/cfg/models/v8/yolov8-C2f-FasterBlock.yaml) # model.load(yolov8n.pt) # loading pretrain weights model.train(datar替换数据集yaml文件地址, # 如果大家任务是其它的ultralytics/cfg/default.yaml找到这里修改task可以改成detect, segment, classify, pose cacheFalse, imgsz640, epochs150, single_clsFalse, # 是否是单类别检测 batch4, close_mosaic10, workers0, device0, optimizerSGD, # using SGD # resume, # 如过想续训就设置last.pt的地址 ampFalse, # 如果出现训练损失为Nan可以关闭amp projectruns/train, nameexp, )5.3 RIDNet 的训练过程截图​五、本文总结到此本文的正式分享内容就结束了在这里给大家推荐我的YOLOv26改进有效涨点专栏本专栏目前为新开的平均质量分98分后期我会根据各种最新的前沿顶会进行论文复现也会对一些老的改进机制进行补充如果大家觉得本文帮助到你了订阅本专栏关注后续更多的更新~专栏链接YOLOv26有效涨点专栏包含Conv、注意力机制、主干/Backbone、损失函数、优化器、后处理等改进机制​

相关新闻

最新新闻

科研配图告别多软件折腾!paperxie AI 科研绘图三步式制图功能全解析

科研配图告别多软件折腾!paperxie AI 科研绘图三步式制图功能全解析

paperxie-免费查重复率aigc检测/开题报告/毕业论文/智能排版/文献综述/科研绘图科研绘图 - PaperXie智能写作PaperXie免费论文查重检测-首款免费论文检测软件,为毕业生提供专业的论文重复率检测、论文降重、Aigc检测、智能排版 、论文写作等一站式服务。https://www.paperxie.c…

2026/7/3 3:22:36
Qt实现简易计数器(点击累加/清零功能)【完整源码】

Qt实现简易计数器(点击累加/清零功能)【完整源码】

一、项目简介 超适合新手的 Qt 入门小案例,实现数字计数器功能,点击按钮数字累加、一键清零,界面简洁、代码极少,非常适合当做入门第一篇技术博客。 实现功能: 点击累加按钮,数字 1点击清零按钮&#xff0c…

2026/7/3 3:22:36
Koji Build 命令参数深度解析:从入门到精通

Koji Build 命令参数深度解析:从入门到精通

在 Koji 构建系统中,koji build 是最核心、最常用的命令之一。理解其各个参数的含义和应用场景,是每一位 Linux 发行版构建工程师和包维护者的必修课。本文将逐一拆解 koji build 的每个参数,并重点剖析 --scratch 参数的本质、NVR 唯一性规则…

2026/7/3 3:22:36
2026年7月亲测:深圳高空吊装企业性价比分享

2026年7月亲测:深圳高空吊装企业性价比分享

行业痛点分析深圳作为一座现代化都市,高楼林立,对高空吊装服务的需求日益增长。然而,面对市场中众多的吊装公司,如何选择一家既专业又具有高性价比的服务商成为了用户的一大难题。在实际操作中,许多用户反映遇到过报价…

2026/7/3 3:22:36
字典、集合你真的了解吗?

字典、集合你真的了解吗?

前言 字典(dict)和集合(set),字典和集合在Python被广泛使用,并且性能进行了高度优化。字典是一系列由键(key)和值(value)配对组成的元素的集合。 Python 3.7 及之后,dict 是保证插入顺序的。相比于列表和元组,字典的性能更优,特别对于查找、…

2026/7/3 3:22:36
Python爬虫经典案例第58篇:数据竞赛平台爬取——Kaggle数据采集实战

Python爬虫经典案例第58篇:数据竞赛平台爬取——Kaggle数据采集实战

1. 项目背景与目标 1.1 Kaggle简介 Kaggle是全球最大的数据科学竞赛平台,由Google旗下的Alphabet公司拥有。它为数据科学家和机器学习工程师提供了一个展示技能、学习新知识和解决实际问题的平台。 网站特点: 数千个数据科学竞赛 海量数据集(超过500TB) 活跃的社区(超过…

2026/7/3 3:17:35

周新闻

月新闻