【CVPR2017】AOD-Net:端到端的除雾网络(原理&实操)

简介: 【CVPR2017】AOD-Net:端到端的除雾网络(原理&实操)

前言

  由于AOD-Net网络是2017年的顶刊论文,在网上也有相当多的讲解,因此本文中将不会过多赘述论文中的内容,仅摘取精华进行讲解。

导读

  AOD-Net 是一种用于图像去雾的深度神经网络模型,旨在通过对图像进行学习和分析,从中提取出场景中的深度信息,从而去除图像中的雾霾。AOD-Net 的全称为 "All-in-One Dehazing Network",是由学者们在研究图像去雾的过程中提出的一种全新的深度神经网络模型。该模型采用了基于 CNN 的网络结构,在学习和分析图像的同时,还能够提取出场景中的深度信息,从而能够更加准确地去除图像中的雾霾。

  相较于传统的图像去雾算法,AOD-Net 具有更高的去雾效果和更快的速度,并且能够适应各种不同的场景和光照条件。因此,AOD-Net 在图像去雾领域具有广泛的应用前景,并且已经被广泛地应用于实际的图像处理任务中。

原理

  AOD-Net其原理基于自适应的最优估计理论和深度学习技术。AOD-Net的设计思想是通过将自适应最优估计理论引入深度学习框架中,实现图像去噪的自适应性和最优性。


image.png

结构组成

  具体来说,AOD-Net由两个子网络组成,即噪声估计网络和噪声去除网络。噪声估计网络用于估计图像中的噪声水平,而噪声去除网络则根据噪声估计网络输出的噪声水平信息,以及图像本身的特征,对图像进行去噪处理。

  AOD-Net的噪声估计网络使用一个类似于U-Net的架构,从原始图像中提取特征并预测噪声的分布。在噪声去除网络中,使用残差网络的结构进行去噪处理,同时使用一个可学习的标准化层来适应预测的噪声水平。

AOD-Net的优点在于它能够自适应地估计噪声水平,从而在不同的噪声水平下进行图像去噪,同时具有较高的去噪效果和计算效率。

代码

  下面是使用torch框架实现的AOD-Net网络结构

ini

复制代码

import torch
import torch.nn as nn
class AODNet(nn.Module):
   def __init__(self):
      super(AODNet, self).__init__()
      self.relu = nn.ReLU(inplace=True)
   
      self.conv1 = nn.Conv2d(3, 3, 1, 1, 0, bias=True)
      self.conv2 = nn.Conv2d(3, 3, 3, 1, 1, bias=True)
      self.conv3 = nn.Conv2d(6, 3, 5, 1, 2, bias=True)
      self.conv4 = nn.Conv2d(6, 3, 7, 1, 3, bias=True)
      self.conv5 = nn.Conv2d(12, 3, 3, 1, 1, bias=True)
      
   def forward(self, x):
      x1 = self.relu(self.conv1(x))
      x2 = self.relu(self.conv2(x1))
      concat1 = torch.cat((x1, x2), 1)
      x3 = self.relu(self.conv3(concat1))
      concat2 = torch.cat((x2, x3), 1)
      x4 = self.relu(self.conv4(concat2))
      concat3 = torch.cat((x1, x2, x3, x4), 1)
      x5 = self.relu(self.conv5(concat3))
      clean_image = self.relu((x5 * x) - x5 + 1) 
      
      return clean_image

结构示例图

image.png

精髓部分

  AOD-Net主要精髓是AOD-Net通过自适应去模糊和多尺度处理的结合,能够在不同场景下有效地提高图像去模糊的效果,具有较高的实用性和普适性。

  具体来说,AOD-Net采用了一个深度卷积神经网络,通过输入模糊图像和一个预先设定的点扩散函数(PSF),输出一张更加清晰的图像。网络架构包含两个主要组成部分:自适应去模糊模块和多尺度处理模块。

  AOD-Net自适应去模糊模块是AOD-Net的核心,它可以根据输入的模糊图像和PSF自适应地学习一个去模糊滤波器,用于恢复更清晰的图像。这个模块中采用了自适应残差学习机制,能够使网络在学习过程中自动选择最优的滤波器。此外,为了保证网络的泛化能力和稳定性,自适应去模糊模块还采用了一些特殊的技巧,例如局部标准化和正则化。

  AOD-Net多尺度处理模块则可以在不同的尺度上处理输入图像,从而有效地提高去模糊效果。具体来说,AOD-Net使用了一个金字塔结构,将输入图像按照不同的尺度进行下采样,并分别输入自适应去模糊模块进行处理。之后,网络将不同尺度的输出图像进行上采样和融合,得到最终的去模糊结果。

实操

  在实操中我将分模块的讲解如何运用网络训练一个自己的除雾网络以及进行ORT推理,在GITHUB上也有相当多的关于AOD-NET的代码,我这里也有一份代码放置在github上,欢迎大家自取。这里主要讲解数据集的准备以及使用ort推理。

数据集的准备

  由于我们需要使用该网络,因此数据集是必不可少的,所以我们可以将本地的一些图像进行生成雾图加雾处理,然后将原图和含有雾的图像分成两个文件夹放置起来即可。

ini

复制代码

import math
import os
import random
import cv2
import numpy as np
from numba import jit
@jit(nopython=True)
def fog(j, center0, l, center1, size, beta):
    d = -0.04 * math.sqrt((j - center0) ** 2 + (l - center1) ** 2) + size
    td = math.exp(-beta * d)
    return d, td
def put_fog(raw_img_path, fog_img_path):
    img = cv2.imread(raw_img_path)
    img_f = img / 255.0
    (row, col, chs) = img.shape
    A = random.uniform(0.45, 0.65)  # 亮度
    beta = random.uniform(0.03, 0.075)  # 亮度
    max_rc = max(row, col)
    size = math.sqrt(max_rc)  # 雾化尺寸
    center = (row // 2, col // 2)  # 雾化中心
    for j in range(row):
        for l in range(col):
            center0 = center[0]
            center1 = center[1]
            d, td = fog(j, center0, l, center1, size, beta)
            img_f[j][l][:] = img_f[j][l][:] * td + A * (1 - td)
    out_img = (img_f * 255).astype(np.uint8)
    cv2.imwrite(fog_img_path, out_img)
    print("---------------------------------")
def ChangeImgName(ImgName, NewName):
    old_img = cv2.imread(ImgName)
    cv2.imwrite(NewName, old_img)
if __name__ == '__main__':
    # demo()
    path = "C:/Users/kiven/Desktop/AOD//data/hazy/"
    fog_path = "C:/Users/kiven/Desktop/AOD//data/1/"
    name_list = os.listdir(path)
    we = "_1_1_2"
    for name in name_list:
        imgname = name[0:-4] + we + ".jpg"
        ChangeImgName(path + name, fog_path+ imgname)
        # put_fog(path+name, fog_path+name)

pth2onnx

  我们新建一个.py文件对训练得到的pth权重进行转化,为了后期能够摆脱torch的安装以及可在边缘设备上运行,这里我们需要明确的是网络的输入大小以及输入输出的名字。

ini

复制代码

import torch
import torch.onnx
def pth_to_onnx(input, checkpoint, onnx_path, input_names,output_names):
    if not onnx_path.endswith('.onnx'):
        print('Warning!')
        return 0
    model = torch.load('saved_models/dehaze_net_epoch_17.pth', map_location=torch.device('cpu'))
    # #指定模型的输入,以及onnx的输出路径
    torch.onnx.export(model, input, onnx_path, verbose=True, input_names=input_names,
                      output_names=output_names)  # 指定模型的输入,以及onnx的输出路径
if __name__ == '__main__':
    checkpoint = './saved_models/dehaze_net_epoch_17.pth'
    onnx_path = './dehaze_net.onnx'
    input = torch.randn(1, 3, 450, 600)
    input_names = ['input']
    output_names = ['output']
    pth_to_onnx(input, checkpoint, onnx_path, input_names, output_names)

ORT推理

  在ORT中我们主要工作是将torch中的一些操作替换为numpy的操作:

  1. 采用pillow读取图像;
  2. 转换为numpy然后归一化0~1之间;
  3. 数据转换为float32格式;
  4. 在位置0维度上添加一个维度;
  5. 使用ort读取网络并推理(推理结果是一个list)
  6. 获取推理结果后取出结果numpy(shape= 1,3,450,600)
  7. 去除shape[0]的地方
  8. 显示结果图

ini

复制代码

import numpy as np
from PIL import Image
import onnxruntime as ort
import matplotlib.pyplot as plt
def dehaze_image(image_name):
    data_hazy = Image.open(image_name)
    data_hazy = np.array(data_hazy) / 255.0
    original_img = data_hazy.copy()
    data_hazy = np.array(data_hazy, dtype=np.float32)
    data_hazy = np.transpose(data_hazy, (2, 0, 1))
    data_hazy = np.expand_dims(data_hazy, 0)
    bolb = data_hazy
    input_name = 'input'
    output_name = 'output'
    dehaze_net = ort.InferenceSession("./dehaze_net.onnx", providers=ort.get_available_providers())
    netOutputImg = dehaze_net.run([output_name], {input_name: bolb})
    pdata = netOutputImg[0]
    clean_image = pdata.squeeze()
    clean_image = np.swapaxes(clean_image, 0, 1)
    clean_image = np.swapaxes(clean_image, 1, 2)
    plt.subplot(1, 2, 1)
    plt.imshow(original_img)
    plt.axis('off')
    plt.title('Original Image')
    plt.subplot(1, 2, 2)
    plt.imshow(clean_image)
    plt.axis('off')
    plt.title('Dehaze Image')
    plt.show()
if __name__ == '__main__':
    img_name = './test_images/test0.png'
    dehaze_image(img_name)

结语

  虽然AOD-Net已经取得了很好的去雾效果,但是还有很多挑战需要克服,例如在复杂场景下的去雾效果提升,以及对运动模糊等噪声的抵抗能力。未来的研究将不断推动图像去雾技术的发展,希望这篇文章能为读者们对图像去雾技术的理解和应用提供一些帮助。


相关文章
|
5天前
|
并行计算 安全 网络协议
探索未来网络:量子互联网的原理与应用
本文深入探讨了量子互联网的基本概念、技术原理及其潜在应用。通过对量子纠缠、量子叠加和量子隐形传态等核心概念的解释,文章展示了量子互联网如何利用量子力学特性来实现超高速、超高安全性的通信。此外,还讨论了量子互联网在金融、医疗、国防等领域的应用前景,以及当前面临的技术挑战和未来的发展方向。
|
26天前
|
机器学习/深度学习 人工智能 自然语言处理
深度学习的奥秘:探索神经网络的核心原理
本文将深入浅出地介绍深度学习的基本概念,包括神经网络的结构、工作原理以及训练过程。我们将从最初的感知机模型出发,逐步深入到现代复杂的深度网络架构,并探讨如何通过反向传播算法优化网络权重。文章旨在为初学者提供一个清晰的深度学习入门指南,同时为有经验的研究者回顾和巩固基础知识。
43 11
|
2月前
|
机器学习/深度学习 人工智能 自然语言处理
深度学习中的自适应神经网络:原理与应用
【8月更文挑战第14天】在深度学习领域,自适应神经网络作为一种新兴技术,正逐渐改变我们处理数据和解决问题的方式。这种网络通过动态调整其结构和参数来适应输入数据的分布和特征,从而在无需人工干预的情况下实现最优性能。本文将深入探讨自适应神经网络的工作原理、关键技术及其在多个领域的实际应用,旨在为读者提供一个全面的视角,理解这一技术如何推动深度学习向更高效、更智能的方向发展。
|
5天前
|
机器学习/深度学习 人工智能 自然语言处理
深度学习的奥秘:探索神经网络背后的原理与实践
【9月更文挑战第29天】本文将带你深入理解深度学习的核心概念,从基础理论到实际应用,逐步揭示其神秘面纱。我们将探讨神经网络的工作原理,并通过实际代码示例,展示如何构建和训练一个简单的深度学习模型。无论你是初学者还是有一定经验的开发者,这篇文章都将为你提供宝贵的知识和技能。
14 2
|
28天前
|
网络架构
.NET 网络唤醒
【9月更文挑战第5天】在网络管理中,.NET 可以实现 Wake-on-LAN,即通过发送特定数据包(魔术包)唤醒睡眠或关机状态的计算机。首先需引入命名空间(System.Net, System.Net.Sockets),然后编写 WakeUpComputer 方法,构造并发送含有目标计算机 MAC 地址的魔术包,最后调用此方法即可。使用前,请确认目标计算机及网络设备支持此功能。
20 12
|
25天前
|
机器学习/深度学习 人工智能 自然语言处理
深度剖析深度神经网络(DNN):原理、实现与应用
本文详细介绍了深度神经网络(DNN)的基本原理、核心算法及其具体操作步骤。DNN作为一种重要的人工智能工具,通过多层次的特征学习和权重调节,实现了复杂任务的高效解决。文章通过理论讲解与代码演示相结合的方式,帮助读者理解DNN的工作机制及实际应用。
|
21天前
|
网络协议 Linux 应用服务中间件
Socket通信之网络协议基本原理
【9月更文挑战第14天】网络协议是机器间交流的约定格式,确保信息准确传达。主要模型有OSI七层与TCP/IP模型,通过分层简化复杂网络环境。IP地址全局定位设备,MAC地址则在本地网络中定位。网络分层后,数据包层层封装,经由不同层次协议处理,最终通过Socket系统调用在应用层解析和响应。
|
22天前
|
网络协议 网络架构 数据格式
TCP/IP基础:工作原理、协议栈与网络层
TCP/IP(传输控制协议/互联网协议)是互联网通信的基础协议,支持数据传输和网络连接。本文详细阐述了其工作原理、协议栈构成及网络层功能。TCP/IP采用客户端/服务器模型,通过四个层次——应用层、传输层、网络层和数据链路层,确保数据可靠传输。网络层负责IP寻址、路由选择、分片重组及数据包传输,是TCP/IP的核心部分。理解TCP/IP有助于深入掌握互联网底层机制。
112 2
|
2月前
|
存储 算法 Java
深入理解.NET中的托管堆及其工作原理
【8月更文挑战第31天】
28 1
|
2月前
|
缓存 网络协议 算法
网络编程原理
网络编程原理
下一篇
无影云桌面