一、本文介绍
本文给大家带来的改进机制是利用AODNet图像去雾网络结合PONO机制实现二次增强,我将该网络结合YOLOv5针对图像进行去雾检测(也适用于一些模糊场景,图片不清晰的检测),同时本文的内容不影响其它的模块改进可以作为工作量凑近大家的论文里,非常的适用,图像去雾检测为群友最近提出的需要的改进,在开始之前给大家推荐一下我的专栏,本专栏每周更新3-10篇最新前沿机制 | 包括二次创新全网无重复,以及融合改进(大家拿到之后添加另外一个改进机制在你的数据集上实现涨点即可撰写论文),还有各种前沿顶会改进机制 |,更有包含我所有附赠的文件(文件内集成我所有的改进机制全部注册完毕可以直接运行)和交流群和视频讲解提供给大家。
👑欢迎大家订阅我的专栏一起学习YOLO👑
专栏回顾:YOLOv5改进专栏——持续复现各种顶会内容——内含100+创新
目录
一、本文介绍
二、原理介绍
三、核心代码
四、添加教程
4.1 修改一
4.2 修改二
4.3 修改三
五、AODNet-PONO-Net的yaml文件和运行记录
5.1 AODNet-PONO-Net的yaml文件
5.2 训练过程截图
五、本文总结
二、原理介绍
官方论文地址: 官方论文地址点击即可跳转
官方代码地址: 官方代码地址点击即可跳转
摘要:这篇论文提出了一种名为全能去雾网络(AOD-Net)的图像去雾模型,该模型是基于重新制定的大气散射模型并利用卷积神经网络(CNN)构建的。与大多数先前的模型不同,AOD-Net不是分别估计传输矩阵和大气光,而是直接通过一个轻量级的CNN生成清晰图像。这种新颖的端到端设计使得将AOD-Net嵌入到其他深度模型中变得简单,例如,用于提升雾霾图像上高级任务性能的Faster R-CNN。在合成和自然雾霾图像数据集上的实验结果证明了我们在峰值信噪比(PSNR)、结构相似性指数(SSIM)和主观视觉质量方面超越了最先进技术的性能。此外,当将AOD-Net与Faster R-CNN结合并从头到尾进行联合训练时,我们见证了雾霾图像上对象检测性能的显著提升。
AOD-Net是一个端到端的可训练去雾模型,直接从有雾图像产生清晰图像,而不是依赖于任何单独和中间参数估计步骤。基于重新公式化的大气散射模型设计,与现有工作共享相同的物理基础,但以一种“更端到端”的方式将其所有参数估计在一个统一模型中完成
主要创新点
- 端到端去雾模型:首次提出一个端到端训练的去雾模型,直接从雾图像生成清晰图像,避免了传统方法中估计传输矩阵和大气光的独立步骤。
- 与高级视觉任务的结合:首次量化研究去雾质量如何影响后续高级视觉任务的性能,为比较去雾结果提供了一种新的客观标准。此外,AOD-Net可以无缝地与其他深度模型嵌入,形成一个在有雾图像上执行高级任务的流水线,通过端到端的联合调优进一步提升性能。
个人总结:AOD-Net能够一步到位地把雾气重的照片变清晰,而不像以前的方法那样需要分好几步小心翼翼地处理。简单来说,AOD-Net就是通过学习雾中的图片和清晰图片之间的差别,找到一种直接去除雾气的捷径,使得图片恢复清晰,同时也帮助计算机更好地理解图片内容。
目录
一、本文介绍
二、原理介绍
三、核心代码
四、添加教程
4.1 修改一
4.2 修改二
4.3 修改三
五、AODNet-PONO-Net的yaml文件和运行记录
5.1 AODNet-PONO-Net的yaml文件
5.2 训练过程截图
五、本文总结
三、核心代码
核心代码的使用方式看章节四!
import torch
import torch.nn as nn
import torch.nn.functional as F
import torch
torch.autograd.set_detect_anomaly(True)
__all__ = ['AOD_pono_net']
class AODnet(nn.Module):
def __init__(self):
super(AODnet, self).__init__()
self.conv1 = nn.Conv2d(in_channels=3, out_channels=3, kernel_size=1, stride=1, padding=0)
self.conv2 = nn.Conv2d(in_channels=3, out_channels=3, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(in_channels=6, out_channels=3, kernel_size=5, stride=1, padding=2)
self.conv4 = nn.Conv2d(in_channels=6, out_channels=3, kernel_size=7, stride=1, padding=3)
self.conv5 = nn.Conv2d(in_channels=12, out_channels=3, kernel_size=3, stride=1, padding=1)
self.b = 1
def forward(self, x):
x1 = F.relu(self.conv1(x))
x2 = F.relu(self.conv2(x1))
cat1 = torch.cat((x1, x2), 1)
x3 = F.relu(self.conv3(cat1))
cat2 = torch.cat((x2, x3), 1)
x4 = F.relu(self.conv4(cat2))
cat3 = torch.cat((x1, x2, x3, x4), 1)
k = F.relu(self.conv5(cat3))
if k.size() != x.size():
raise Exception("k, haze image are different size!")
output = k * x - k + self.b
return F.relu(output)
class AOD_pono_net(nn.Module):
def __init__(self):
super(AOD_pono_net, self).__init__()
self.conv1 = nn.Conv2d(in_channels=3, out_channels=3, kernel_size=1, stride=1, padding=0)
self.conv2 = nn.Conv2d(in_channels=3, out_channels=3, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(in_channels=6, out_channels=3, kernel_size=5, stride=1, padding=2)
self.conv4 = nn.Conv2d(in_channels=6, out_channels=3, kernel_size=7, stride=1, padding=3)
self.conv5 = nn.Conv2d(in_channels=12, out_channels=3, kernel_size=3, stride=1, padding=1)
self.b = 1
self.pono = PONO(affine=False)
self.ms = MS()
def forward(self, x):
x1 = F.relu(self.conv1(x))
x2 = F.relu(self.conv2(x1))
cat1 = torch.cat((x1, x2), 1)
x1, mean1, std1 = self.pono(x1)
x2, mean2, std2 = self.pono(x2)
x3 = F.relu(self.conv3(cat1))
cat2 = torch.cat((x2, x3), 1)
x3 = self.ms(x3, mean1, std1)
x4 = F.relu(self.conv4(cat2))
x4 = self.ms(x4, mean2, std2)
cat3 = torch.cat((x1, x2, x3, x4), 1)
k = F.relu(self.conv5(cat3))
if k.size() != x.size():
raise Exception("k, haze image are different size!")
output = k * x - k + self.b
output = F.relu(output)
return output
class PONO(nn.Module):
def __init__(self, input_size=None, return_stats=False, affine=True, eps=1e-5):
super(PONO, self).__init__()
self.return_stats = return_stats
self.input_size = input_size
self.eps = eps
self.affine = affine
if affine:
self.beta = nn.Parameter(torch.zeros(1, 1, *input_size))
self.gamma = nn.Parameter(torch.ones(1, 1, *input_size))
else:
self.beta, self.gamma = None, None
def forward(self, x):
mean = x.mean(dim=1, keepdim=True)
std = (x.var(dim=1, keepdim=True) + self.eps).sqrt()
x = (x - mean) / std
if self.affine:
x = x * self.gamma + self.beta
return x, mean, std
class MS(nn.Module):
def __init__(self, beta=None, gamma=None):
super(MS, self).__init__()
self.gamma, self.beta = gamma, beta
def forward(self, x, beta=None, gamma=None):
beta = self.beta if beta is None else beta
gamma = self.gamma if gamma is None else gamma
if gamma is not None:
y = x.mul(gamma) # 使用非原地操作mul
else:
y = x # 如果不乘gamma,保持y不变
if beta is not None:
y = y.add(beta) # 使用非原地操作add
return y
if __name__ == "__main__":
# Generating Sample image
image_size = (1, 3, 640, 640)
image = torch.rand(*image_size)
out = AOD_pono_net()
out = out(image)
print(out.size())
四、添加教程
4.1 修改一
第一还是建立文件,我们找到如下yolov5-master/models文件夹下建立一个目录名字呢就是'modules'文件夹(用群内的文件的话已经有了无需新建)!然后在其内部建立一个新的py文件将核心代码复制粘贴进去即可。
4.2 修改二
第二步我们在该目录下创建一个新的py文件名字为'__init__.py'(用群内的文件的话已经有了无需新建),然后在其内部导入我们的检测头如下图所示。
4.3 修改三
第三步我门中到如下文件'yolov5-master/models/yolo.py'进行导入和注册我们的模块(用群内的文件的话已经有了无需重新导入直接开始第四步即可)!
从今天开始以后的教程就都统一成这个样子了,因为我默认大家用了我群内的文件来进行修改!!
到此就修改完成了,大家可以复制下面的yaml文件运行,无需修改parse_model方法。。
五、AODNet-PONO-Net的yaml文件和运行记录
5.1 AODNet-PONO-Net的yaml文件
# YOLOv5 🚀 by Ultralytics, AGPL-3.0 license
# Parameters
nc: 80 # number of classes
depth_multiple: 0.33 # model depth multiple
width_multiple: 0.25 # layer channel multiple
anchors:
- [10,13, 16,30, 33,23] # P3/8
- [30,61, 62,45, 59,119] # P4/16
- [116,90, 156,198, 373,326] # P5/32
# YOLOv5 v6.0 backbone
backbone:
# [from, number, module, args]
[[-1, 1, AOD_pono_net, []], # 0-P1/2
[-1, 1, Conv, [64, 6, 2, 2]], # 1-P1/2
[-1, 1, Conv, [128, 3, 2]], # 2-P2/4
[-1, 3, C3, [128]],
[-1, 1, Conv, [256, 3, 2]], # 4-P3/8
[-1, 6, C3, [256]],
[-1, 1, Conv, [512, 3, 2]], # 6-P4/16
[-1, 9, C3, [512]],
[-1, 1, Conv, [1024, 3, 2]], # 8-P5/32
[-1, 3, C3, [1024]],
[-1, 1, SPPF, [1024, 5]] # 10
]
# YOLOv5 v6.0 head
head:
[[-1, 1, Conv, [512, 1, 1]],
[-1, 1, nn.Upsample, [None, 2, 'nearest']],
[[-1, 7], 1, Concat, [1]], # cat backbone P4
[-1, 3, C3_MSDA, [512, False]], # 14
[-1, 1, Conv, [256, 1, 1]],
[-1, 1, nn.Upsample, [None, 2, 'nearest']],
[[-1, 5], 1, Concat, [1]], # cat backbone P3
[-1, 3, C3_MSDA, [256, False]], # 18 (P3/8-small)
[-1, 1, Conv, [256, 3, 2]],
[[-1, 15], 1, Concat, [1]], # cat head P4
[-1, 3, C3_MSDA, [512, False]], # 21 (P4/16-medium)
[-1, 1, Conv, [512, 3, 2]],
[[-1, 11], 1, Concat, [1]], # cat head P5
[-1, 3, C3_MSDA, [1024, False]], # 24 (P5/32-large)
[[18, 21, 24], 1, Detect, [nc, anchors]], # Detect(P3, P4, P5)
]
5.2 训练过程截图
五、本文总结
到此本文的正式分享内容就结束了,在这里给大家推荐我的YOLOv8改进有效涨点专栏,本专栏目前为新开的平均质量分98分,后期我会根据各种最新的前沿顶会进行论文复现,也会对一些老的改进机制进行补充,如果大家觉得本文帮助到你了,订阅本专栏,关注后续更多的更新~
专栏回顾:YOLOv5改进专栏——持续复现各种顶会内容——内含100+创新