Densely Connected Pyramid Dehazing Network

Abstract

提出了一种新的端到端的单幅图像去雾方法,称为稠密连接金字塔去雾网络(DCPDN),该方法可以联合学习透射图、大气光照和去雾。通过将大气散射模型直接嵌入到网络中,实现了端到端的学习,从而保证了所提方法严格遵循物理驱动的散射模型进行去雾。受密集网络能够最大化不同层次沿着信息流的启发,提出了一种新的边缘保持密集连接编解码器结构,并采用多级金字塔池模块来估计传输图。利用新引入的保边损失函数对网络进行优化。为了进一步融合估计的透射图与去雾结果之间的互结构信息,提出了一种基于生成对抗网络框架的联合鉴别器,用于判断对应的去雾图像与估计的透射图的真伪。进行消融研究以证明在估计的透射图和去雾结果下评价的每个模块的有效性。大量实验表明,该方法与现有方法相比有显著的改进。代码和数据集可从以下网址获取:https://github.com/hezhangsprinter/DCPDN

1. Introduction

在严重的雾霾条件下,大气中的漂浮颗粒物,如黄昏和烟雾,极大地吸收和散射光,导致图像质量下降。这些退化又可能影响许多计算机视觉系统的性能,例如分类和检测。为了克服由雾引起的退化,文献[33、5、42、3、13、21、27、51、24、58、8、10、9、34]中已经提出了基于图像和视频的雾去除算法。

由于雾的存在而导致的图像劣化(大气散射模型)在数学上被公式化为

 其中I是观察到的雾图像,J是真实场景辐射率,A是全局大气光,指示环境光的强度,t是透射图,z是像素位置。透射贴图是与距离相关的因素,它会影响到达相机传感器的光线比例。当大气光A均匀时,透射图可以表示为t(z)=e^{-\beta d(z)},其中β表示大气的衰减系数,d是场景深度。在单幅图像去雾中,给定I,目标是估计J。

可从公式中观察到。1在去雾过程中存在两个重要方面:(1)准确估计透射图;(2)准确估计大气光。除了几项侧重于估计大气光的工作[4,40]外,大多数其他算法更侧重于准确估计透射图,并且它们在估计大气光时利用经验法则[13,29,33,41]。这主要是由于通常相信透射图的良好估计将导致更好的去雾。这些方法可大致分为两大类:基于先验的方法和基于学习的方法。基于先验的方法通常利用不同的先验来表征传输图,例如暗通道先验[13],对比度颜色线[10]和Haze-line先验[3],而基于学习的方法,例如基于卷积神经网络(CNN)的方法,试图直接从训练数据中学习传输图[42,33,5,51,24]。一旦估计了透射图和大气光,就可以如下恢复去雾图像

虽然基于学习的方法已经取得了巨大的进步,但是一些因素阻碍了这些方法的性能,并且结果远非最优。这主要是因为:1.透射图估计的不准确性转化为低质量的去雾结果。2.现有的方法没有利用端到端的学习,并且不能捕捉透射图、大气光和去雾图像之间的内在关系。不相交的优化可能会妨碍整体去雾性能。最近,在[24]中提出了一种联合优化整个除雾网络的方法。这是通过利用线性变换将透射图和大气光嵌入到一个变量中,然后学习轻量级CNN来恢复干净的图像来实现的。

在本文中,我们采取了一种不同的方法来解决图像去雾的端到端学习。特别地,我们提出了一种新的图像去雾架构,称为密集连接金字塔去雾网络(DCPDN),其可以被联合优化以通过遵循图像退化模型方程同时估计透射图、大气光以及图像去雾。1(见图2)。换句话说,端到端学习是通过嵌入等式1通过深度学习框架提供的数学运算模块直接进入网络。然而,训练这样一个复杂的网络(具有三个不同的任务)是非常具有挑战性的。为了简化训练过程并加速网络收敛,我们利用了一种分阶段学习技术,首先逐步优化网络的每个部分,然后联合优化整个网络。为了确保估计的透射图在去雾时保持锐利的边缘并避免光晕伪影,基于梯度算子和CNN结构的前几层可以充当边缘提取器的观察,提出了一种新的边缘保持损失函数。此外,提出了一种具有多级池模块的密集连接的编码器-解码器网络,以利用来自不同级别的特征来估计传输图。为了利用透射图和去雾图像之间的结构关系,提出了一种基于联合鉴别器的生成对抗网络(GAN)。联合鉴别器鉴别一对估计的透射图和去雾图像是真实的还是假对。为了保证大气光也可以在整个结构内被优化,采用U网[35]来估计均匀大气光图。图1中所示的是使用所提出的方法的样本去雾图像。

本文主要贡献如下:

·提出了一种新型的端到端联合优化去雾网络。这可以通过嵌入公式1通过数学运算模块直接导入优化框架。因此,它允许网络联合地估计透射图、大气光和去雾图像。整个网络通过分阶段学习方法进行训练。

·提出了一种保持边缘的金字塔密集连接编解码器网络,用于精确估计传输图。进一步,利用新提出的边缘保持损失函数对该算法进行了优化。

·由于估计的透射图和去雾图像的结构高度相关,我们利用GAN框架内的联合鉴别器来确定成对样本(即透射图和去雾图像)是否来自数据分布。

·在两个合成数据集和一个真实世界图像数据集上进行了广泛的实验。此外,还与几种最新技术水平的方法进行了比较。此外,进行了消融研究,以证明所提出的网络中的不同模块所获得的改进。

 2. Related Work

Single Image Dehazing.

单幅图像去雾是一个高度不适定的问题。各种基于先验和基于学习的手工方法已经被开发出来以解决这个问题。

基于先验的手工制作:Fattal [9]提出了一种基于物理的方法,通过估计场景的反照率。由于在有雾条件下拍摄的图像总是缺乏颜色对比度,Tan [41]等人提出了一种基于块的对比度最大化方法。在[22]中,Kratz和Nishino提出了一个因子MRF模型来估计反照率和深度场。受晴朗天气下户外物体至少有一个颜色通道明显较暗这一观察结果的启发,He等人在[13]中提出了暗信道模型来估计透射图。最近,Fattal [10]提出了一种色线方法,该方法基于小图像块通常在RGB颜色空间中呈现一维分布的观察结果。类似地,Berman等人[3]提出了在表征干净图像之前的非局部补丁。

学习型:与使用不同先验来估计传输图的上述方法中的一些不同,Cai等人[5]引入了端到端CNN网络,用于利用新颖的BReLU单元来估计传输。最近,Ren等人[33]提出了一种多尺度深度神经网络来估计透射图。这些方法的局限性之一是它们通过仅考虑它们的CNN框架中的传输图来限制它们的能力。针对这一问题,李.等人[24]提出了一种一体化去雾网络,其中利用线性变换将透射图和大气光编码为一个变量。最近,针对去雾问题的合成和真实世界雾图像的几个基准数据集被引入到社区[53,25]。

Generative Adversarial Networks (GANs).

GAN的概念首先由Goodfellow等人在[12]中提出,以通过经由博弈论极小极大优化框架有效地学习训练图像的分布来合成真实感图像。GAN在合成真实图像方面的成功使得研究人员开始探索各种低级视觉应用的对抗性损失,例如文本到图像合成[32,52,55,6]、图像到图像转换[18,28,46,45,50]、超分辨率[23]、人体姿势估计[31]和其他应用[56,59,38,44]。受这些方法在生成具有精细细节的高质量图像方面的成功启发,我们提出了一种基于联合鉴别器的GAN来细化估计的透射图和去雾图像。

3. Proposed Method

所提出的DCPDN网络架构如图2所示,其由以下四个模块组成:1)金字塔密集连接的透射图估计网络,2)大气光估计网络,3)通过等式2和4)联合鉴别器。在下文中,我们将详细解释这些模块。

图2:本文提出的DCPDN图像去雾方法的概述。DCPDN由四个模块组成:金字塔密集连接传输地图估计网。2. 大气光估计网。3.通过Eq2去雾。4. 联合鉴别器。我们首先使用提出的金字塔密集连接的传输估计网估计传输图,然后使用u -网结构预测大气光。最后,利用估计的透射图和大气光,我们通过公式2估计去雾图像。

Pyramid Densely Connected Transmission Map Estimation Network.

受使用多级特征来估计传输图的先前方法[33,5,42,1,24]的启发,我们提出了利用来自CNN的多个层的特征的密集连接的编码器-解码器结构,其中密集块被用作基本结构。使用密集块的原因在于它可以最大化沿着这些特征的信息流,并通过连接所有层来保证更好的收敛。此外,采用多级金字塔池化模块,通过将“全局”结构信息考虑到优化中来细化学习的特征[57]。为了利用密集网[15]的预定义权重,我们采用来自预训练密集网121的第一Conv层和前三个密集块以及它们对应的下采样操作转换块作为我们的编码器结构。编码部分末端的特征尺寸是输入尺寸的1/32。为了将传输图重建为原始分辨率,我们将五个密集块与细化的上采样过渡块[19,60,54]堆叠作为解码模块。此外,采用具有对应于相同维度的特征的级联。

即使所提出的稠密连接编码器-解码器结构结合了网络内部的不同特征,但单纯的稠密连接结构仍然缺乏不同尺度对象的“全局”结构信息。一个可能的原因是来自不同尺度的特征没有被用于直接估计最终的透射图。为了有效地解决这一问题,采用了多级金字塔池块,以确保不同尺度的特征都嵌入到最终结果中。这是受到在分类和分割任务中使用全局上下文信息的启发[57,48,14]。不是采用非常大的池大小来捕获不同对象之间的更多全局上下文信息[57],而是需要更多的“局部”信息来表征每个对象的“全局”结构。因此,采用池化大小为1/32、1/16、1/8和1/4的四级池化操作。然后,所有四级特征被上采样到原始特征大小,并在最终估计之前与原始特征级联回。图3给出了所提出的金字塔密集连接的传输图估计网络的概观。

Atmospheric Light Estimation Network.

遵循图像退化模型方程:1,我们假设大气光照图A是均匀的[13,5]。类似于先前的工作,预测的大气光A对于给定图像是均匀的。换言之,预测的A是2D图,其中每个像素A(z)具有相同的值(例如,A(z)= c,c为常数)。结果,真实背景A具有与输入图像相同的特征大小,并且A中的像素被填充以相同的值。为了估计大气光,我们采用8块U网[35]结构,其中编码器由四个Conv-BN-Relu块组成,解码器由对称的Dconv-BN-Relu块1组成。

Dehazing via Eq. 2.

为了桥接透射图、大气光和去雾图像之间的关系,并且为了确保整个网络结构对于所有三个任务被联合优化,我们将(2)直接嵌入到整体优化框架中。整个DCPDN结构的概述如图1所示。

3.1. Joint Discriminator Learning

令Gt和Gd分别表示生成透射图和去雾结果的网络。为了细化输出并确保估计的透射图Gt(I)和去雾图像Gd(I)分别与它们对应的地面真值t和J不可区分,我们使用具有新颖的联合鉴别器的GAN [12]。

从(1)以及图4可以观察到,估计的透射图\hat{t}=G_{t}(I)和去雾图像\hat{J}之间的结构信息高度相关。因此,为了利用这两个模态之间的结构信息的依赖性,我们引入联合鉴别器来学习联合分布,以判定对应对(透射图、去雾图像)是真实的还是虚假的。通过利用联合分布优化,可以更好地利用它们之间的结构相关性。与以前的工作类似,对于给定的图像,预测的空气光A是均匀的。换言之,预测的空气光A是2D图,其中每个像素A(z)具有相同的值(例如,A(z)= c,c为常数)。我们提出以下基于联合鉴别器的优化

 在实际应用中,我们将去雾后的图像与估计的透射图连接成一对样本,然后将其馈送到鉴别器。

3.2. Edge-preserving Loss

通常认为,欧几里德损失(L2损失)倾向于雾最终结果。因此,仅L2损失的透射图的不准确估计可能导致细节损失,从而导致去雾图像中的晕圈伪影[16]。为了有效地解决这一问题,提出了一种新的边缘保持损失,其由以下两个观察所激发。1)边缘对应于图像强度中的不连续性,因此其可以由图像梯度表征。2)已知可以在CNN结构的浅(前几个)层中捕获诸如边缘和轮廓的低级特征[47]。换句话说,前几层用作深度网络中的边缘检测器。例如,如果将透射图输入预定义的VGG-16 [37]模型,然后可视化层relu 1 2输出的某些特征,则可以清楚地观察到边缘信息保留在相应的特征图中(见图5)。

 基于这些观察并且受到深度估计中使用的梯度损失[43,26]以及在低级视觉任务中使用感知损失[20,49]的启发,我们提出了由三个不同部分组成的新的边缘保留损失函数:L2误差、双向梯度误差和特征边缘误差,定义如下

 

 3.3. Overall Loss Function

所提出的DCPDN架构使用以下四个损失函数来训练

 3.4. Stage-wise Learning

在实验中,我们发现直接用复损耗Eq. 7从头开始训练整个网络是困难的,并且网络收敛速度很慢。一个可能的原因可能是由于不同任务引起的梯度扩散。例如,来自去雾图像丢失的梯度可能最初“分散”来自透射图丢失的梯度,导致较慢的收敛。为了解决这个问题并加快训练速度,引入了一种阶段式学习策略,该策略已用于不同的应用,如多模型识别[7]和特征学习[2]。因此,训练数据中的信息逐渐呈现给网络。换句话说,不同的任务是逐步学习的。首先,我们通过不同时更新其他任务来分别优化每个任务。在每个任务的“初始化”之后,我们通过联合优化所有三个任务来微调整个网络。

4. Experimental Results

在本节中,我们通过在两个合成数据集和一个真实世界数据集上进行各种实验来证明所提出的方法的有效性。将所有结果与五种最先进的方法进行比较:He等人(CVPR'09)[13],Zhu等人(TIP'15)[58],Ren等人[33](ECCV'16),Berman等人[3,4](CVPR'16和ICCP'17)和Li等人[24](ICCV'17)。此外,我们还进行了消融研究,以证明我们网络中每个模块的有效性。

4.1. Datasets

类似于现有的基于深度学习的去雾方法[33,5,24,51],我们基于(1)合成训练样本{Hazy /Clean /Transmission Map /Atmosphere Light}。合成过程中,随机抽取4种大气光照条件A ∈ [0.5,1]和散射系数β ∈ [0.4,1.6],生成相应的雾天图像、透射图和大气光照图。从NYU-depth 2数据集[30]中选择1000张图像的随机集以生成训练集。因此,总共有4000个训练图像,表示为TrainA。同样,获得了由400(100×4)张图像组成的测试数据集TestA,这些图像也来自NYU-depth 2。我们确保没有测试图像在训练集中。为了证明我们的网络对其他数据集的泛化能力,我们从Middlebury立体数据库(40)[36]和Sun 3D数据集(160)[39]合成了200个{Hazy /Clean /Transmission Map /Atmosphere Light}图像作为TestB集。

4.2. Training Details

 4.3. Ablation Study

为了证明在所提出的网络中引入的每个模块所获得的改进,我们进行了涉及以下五个实验的消融研究:1)密集连接的编解码器结构(DED),2)具有多级金字塔池的密集连接的编码器解码器结构(DED-MLP),3)具有使用L2损失和梯度损失的多级金字塔池的密集连接的编码器解码器结构(DED-MLPGRA),4)具有使用边缘保留损失的多级金字塔池的密集连接编码器解码器结构(DED-MLP-EP),5)所提出的DCPDN,其由具有使用边缘保留损失和联合鉴别器的多级金字塔池的密集连接的编码器解码器结构(DCPDN)组成。

对合成的TestA和TestB数据集进行评价。表1中列出了在各种配置的估计透射图和去雾图像上平均的SSIM结果。目视比较见图6。从图6中,我们得出以下观察结果:1)与(a)和(b)相比,所提出的多级池化模块能够更好地保持具有相对较大规模的对象的“全局”结构。2)与(b)、(c)和(d)相比,边缘保留损失的使用能够更好地细化估计的透射图中的边缘。3)最终的联合鉴别器可以通过确保在结果中捕获精细的结构细节(诸如(e)中的第二行中所示的表格上的小对象的细节)来进一步增强估计的透射图。在测试A和测试B上评价的定量性能也证明了每个模块的有效性。

 4.4. Comparison with state-of-the-art Methods

为了证明所提出的方法实现的改进,将其与最近的最先进的方法[13,58,33,3,4,24]进行比较。在合成和真实的数据集上。

Evaluation on synthetic dataset:

在两个合成数据集TestA和TestB上对所提出的网络进行了评估。由于数据集是合成的,因此可获得地面实况图像和透射图,使我们能够定性和定量地评估性能。图7显示了所提出的方法和五种最新的最先进的方法在测试数据集的两个样本图像上的样本结果。可以观察到,即使先前的方法能够从输入图像中去除雾,但是它们倾向于对图像去雾过度或去雾不足,使得结果较暗或在结果中留下一些雾。相比之下,从我们的结果中可以观察到,它们保留了更清晰的轮廓,颜色失真更少,并且在视觉上更接近地面实况。表2和表3和表4中列出了在试验A和试验B上评价的定量结果,也证明了拟定方法的有效性。

Evaluation on a real dataset:

为了验证所提方法的泛化能力,我们在几幅由之前方法提供的真实世界雾霾图像和从互联网上下载的其他具有挑战性的雾霾图像上对所提方法进行了评估。

图8显示了从之前的方法[33,5,10]中获得的四个样本图像的结果。如图8所示,He等人的方法。[13]和Ren等人的方法。[33](在第四行观察到)倾向于在结果中留下雾,Zhu等人的方法。[58]和Li等人。[24](在第二行显示)倾向于使一些区域变暗(注意背景墙)。Berman等人[3,4]的方法和我们的方法具有最具竞争力的视觉结果。然而,通过仔细观察,我们发现Berman等人[3,4]产生了不真实的颜色偏移,例如第四行中的建筑物颜色。相比之下,我们的方法能够生成真实感的颜色,同时更好地消除雾。这可以通过比较第一行和第二行看出。

我们还对从互联网上下载的几幅雾图像进行了评估。除雾结果如图9所示。从这些结果可以看出,He等人[13]和Berman等人[3,4]的输出遭受颜色失真,如第二和第三行所示。相比之下,我们的方法能够实现更好的去雾,具有视觉上吸引人的结果。

5. Conclusion

提出了一种新的基于深度学习的端到端去雾方法,能够联合优化透射图、大气光照和去雾图像。这是通过将大气图像退化模型直接嵌入到总体优化框架中来实现的。为了有效地估计传输图,提出了一种新的具有多级池模块的密集连接编解码器结构,并通过一种新的边缘保持损失对该网络进行了优化。此外,为了细化细节和利用去雾图像与估计的透射图之间的相互结构相关性,在该方法中引入了一个基于联合鉴别器的GAN框架。通过实验验证了该方法的有效性。

代码

from __future__ import division
import numpy as np
import sys

sys.path.append("./mingqingscript")

import scipy.io as sio
import scipy.ndimage.interpolation
# import scipy.signal

import os

import math
import random

import pdb
import random
import numpy as np
import pickle
import random
import sys
import shutil

import matplotlib.pyplot as plt
import matplotlib.cm as cm
import matplotlib.patches as patches

# torch condiguration
import argparse
from math import log10
# import scipy.io as sio
import numpy as np

import random
from random import uniform
import h5py
import time
import PIL
from PIL import Image

import h5py
import numpy as np
import matplotlib.pyplot as plt

# plt.axis([0, 10, 0, 1])
plt.ion()


# for i in range(10):
#     y = np.random.random()
#     plt.scatter(i, y)
#     plt.pause(0.05)
#
# while True:
#     plt.pause(0.05)
def array2PIL(arr, size):
    mode = 'RGBA'
    arr = arr.reshape(arr.shape[0] * arr.shape[1], arr.shape[2])
    if len(arr[0]) == 3:
        arr = np.c_[arr, 255 * numpy.ones((len(arr), 1), numpy.uint8)]
    return Image.frombuffer(mode, size, arr.tostring(), 'raw', mode, 0, 1)


index = 1
nyu_depth = h5py.File('nyu_depth_v2_labeled.mat', 'r')

directory='facades/train'

if not os.path.exists(directory):
    os.makedirs(directory)


image = nyu_depth['images']
depth = nyu_depth['depths']

img_size = 224

# per=np.random.permutation(1400)
# np.save('rand_per.py',per)
# pdb.set_trace()
total_num = 0
plt.ion()
for index in range(1000):
    index = index
    gt_image = (image[index, :, :, :]).astype(float)
    gt_image = np.swapaxes(gt_image, 0, 2)

    gt_image = scipy.misc.imresize(gt_image, [img_size, img_size]).astype(float)

    gt_image = gt_image / 255


    gt_depth = depth[index, :, :]
    maxhazy = gt_depth.max()
    minhazy = gt_depth.min()
    gt_depth = (gt_depth) / (maxhazy)

    gt_depth = np.swapaxes(gt_depth, 0, 1)
    scale1 = (gt_depth.shape[0]) / img_size
    scale2 = (gt_depth.shape[1]) / img_size

    gt_depth = scipy.ndimage.zoom(gt_depth, (1 / scale1, 1 / scale2), order=1)

    if gt_depth.shape != (img_size, img_size):
        continue

    for j in range(8):

        beta = uniform(0.5, 2)

        tx1 = np.exp(-beta * gt_depth)

        a = 1 - 0.5 * uniform(0, 1)


        m = gt_image.shape[0]
        n = gt_image.shape[1]

        rep_atmosphere = np.tile(np.reshape(A, [1, 1, 3]), [m, n, 1])
        tx1 = np.reshape(tx1, [m, n, 1])

        max_transmission = np.tile(tx1, [1, 1, 3])

        haze_image = gt_image * max_transmission + rep_atmosphere * (1 - max_transmission)

        total_num = total_num + 1
        scipy.misc.imsave('a0.9beta1.29.jpg', haze_image)
        scipy.misc.imsave('gt.jpg', gt_image)

        h5f=h5py.File('./facades/train/'+str(total_num)+'.h5','w')
        h5f.create_dataset('haze',data=haze_image)
        h5f.create_dataset('trans',data=max_transmission)
        h5f.create_dataset('atom',data=rep_atmosphere)
        h5f.create_dataset('gt',data=gt_image)
import torch
import torch.backends.cudnn as cudnn
import torch.nn as nn
import torch.nn.functional as F
import torch
import torch.nn as nn
import torch.nn.functional as F
import torch.utils.model_zoo as model_zoo
from collections import OrderedDict
import torch
import torch.nn as nn
import torch.nn.functional as F
import torch.utils.model_zoo as model_zoo
from collections import OrderedDict
import torchvision.models as models
from torch.autograd import Variable



def conv_block(in_dim,out_dim):
  return nn.Sequential(nn.Conv2d(in_dim,in_dim,kernel_size=3,stride=1,padding=1),
                       nn.ELU(True),
                       nn.Conv2d(in_dim,in_dim,kernel_size=3,stride=1,padding=1),
                       nn.ELU(True),
                       nn.Conv2d(in_dim,out_dim,kernel_size=1,stride=1,padding=0),
                       nn.AvgPool2d(kernel_size=2,stride=2))
def deconv_block(in_dim,out_dim):
  return nn.Sequential(nn.Conv2d(in_dim,out_dim,kernel_size=3,stride=1,padding=1),
                       nn.ELU(True),
                       nn.Conv2d(out_dim,out_dim,kernel_size=3,stride=1,padding=1),
                       nn.ELU(True),
                       nn.UpsamplingNearest2d(scale_factor=2))


def blockUNet1(in_c, out_c, name, transposed=False, bn=False, relu=True, dropout=False):
  block = nn.Sequential()
  if relu:
    block.add_module('%s.relu' % name, nn.ReLU(inplace=True))
  else:
    block.add_module('%s.leakyrelu' % name, nn.LeakyReLU(0.2, inplace=True))
  if not transposed:
    block.add_module('%s.conv' % name, nn.Conv2d(in_c, out_c, 3, 1, 1, bias=False))
  else:
    block.add_module('%s.tconv' % name, nn.ConvTranspose2d(in_c, out_c, 3, 1, 1, bias=False))
  if bn:
    block.add_module('%s.bn' % name, nn.BatchNorm2d(out_c))
  if dropout:
    block.add_module('%s.dropout' % name, nn.Dropout2d(0.5, inplace=True))
  return block

def blockUNet(in_c, out_c, name, transposed=False, bn=False, relu=True, dropout=False):
  block = nn.Sequential()
  if relu:
    block.add_module('%s.relu' % name, nn.ReLU(inplace=True))
  else:
    block.add_module('%s.leakyrelu' % name, nn.LeakyReLU(0.2, inplace=True))
  if not transposed:
    block.add_module('%s.conv' % name, nn.Conv2d(in_c, out_c, 4, 2, 1, bias=False))
  else:
    block.add_module('%s.tconv' % name, nn.ConvTranspose2d(in_c, out_c, 4, 2, 1, bias=False))
  if bn:
    block.add_module('%s.bn' % name, nn.BatchNorm2d(out_c))
  if dropout:
    block.add_module('%s.dropout' % name, nn.Dropout2d(0.5, inplace=True))
  return block


class D1(nn.Module):
  def __init__(self, nc, ndf, hidden_size):
    super(D1, self).__init__()

    # 256
    self.conv1 = nn.Sequential(nn.Conv2d(nc,ndf,kernel_size=3,stride=1,padding=1),
                               nn.ELU(True))
    # 256
    self.conv2 = conv_block(ndf,ndf)
    # 128
    self.conv3 = conv_block(ndf, ndf*2)
    # 64
    self.conv4 = conv_block(ndf*2, ndf*3)
    # 32
    self.encode = nn.Conv2d(ndf*3, hidden_size, kernel_size=1,stride=1,padding=0)
    self.decode = nn.Conv2d(hidden_size, ndf, kernel_size=1,stride=1,padding=0)
    # 32
    self.deconv4 = deconv_block(ndf, ndf)
    # 64
    self.deconv3 = deconv_block(ndf, ndf)
    # 128
    self.deconv2 = deconv_block(ndf, ndf)
    # 256
    self.deconv1 = nn.Sequential(nn.Conv2d(ndf,ndf,kernel_size=3,stride=1,padding=1),
                                 nn.ELU(True),
                                 nn.Conv2d(ndf,ndf,kernel_size=3,stride=1,padding=1),
                                 nn.ELU(True),
                                 nn.Conv2d(ndf, nc, kernel_size=3, stride=1, padding=1),
                                 nn.Tanh())
    """
    self.deconv1 = nn.Sequential(nn.Conv2d(ndf,nc,kernel_size=3,stride=1,padding=1),
                                 nn.Tanh())
    """
  def forward(self,x):
    out1 = self.conv1(x)
    out2 = self.conv2(out1)
    out3 = self.conv3(out2)
    out4 = self.conv4(out3)
    out5 = self.encode(out4)
    dout5= self.decode(out5)
    dout4= self.deconv4(dout5)
    dout3= self.deconv3(dout4)
    dout2= self.deconv2(dout3)
    dout1= self.deconv1(dout2)
    return dout1

class D(nn.Module):
  def __init__(self, nc, nf):
    super(D, self).__init__()

    main = nn.Sequential()
    # 256
    layer_idx = 1
    name = 'layer%d' % layer_idx
    main.add_module('%s.conv' % name, nn.Conv2d(nc, nf, 4, 2, 1, bias=False))

    # 128
    layer_idx += 1
    name = 'layer%d' % layer_idx
    main.add_module(name, blockUNet(nf, nf*2, name, transposed=False, bn=True, relu=False, dropout=False))

    # 64
    layer_idx += 1
    name = 'layer%d' % layer_idx
    nf = nf * 2
    main.add_module(name, blockUNet(nf, nf*2, name, transposed=False, bn=True, relu=False, dropout=False))

    # 32
    layer_idx += 1
    name = 'layer%d' % layer_idx
    nf = nf * 2
    main.add_module('%s.leakyrelu' % name, nn.LeakyReLU(0.2, inplace=True))
    main.add_module('%s.conv' % name, nn.Conv2d(nf, nf*2, 4, 1, 1, bias=False))
    main.add_module('%s.bn' % name, nn.BatchNorm2d(nf*2))

    # 31
    layer_idx += 1
    name = 'layer%d' % layer_idx
    nf = nf * 2
    main.add_module('%s.leakyrelu' % name, nn.LeakyReLU(0.2, inplace=True))
    main.add_module('%s.conv' % name, nn.Conv2d(nf, 1, 4, 1, 1, bias=False))
    main.add_module('%s.sigmoid' % name , nn.Sigmoid())
    # 30 (sizePatchGAN=30)

    self.main = main

  def forward(self, x):
    output = self.main(x)
    return output


class D_tran(nn.Module):
  def __init__(self, nc, nf):
    super(D_tran, self).__init__()

    main = nn.Sequential()
    # 256
    layer_idx = 1
    name = 'layer%d' % layer_idx
    main.add_module('%s.conv' % name, nn.Conv2d(nc, nf, 4, 2, 1, bias=False))

    # 128
    layer_idx += 1
    name = 'layer%d' % layer_idx
    main.add_module(name, blockUNet(nf, nf*2, name, transposed=False, bn=True, relu=False, dropout=False))

    # 64
    layer_idx += 1
    name = 'layer%d' % layer_idx
    nf = nf * 2
    main.add_module(name, blockUNet(nf, nf*2, name, transposed=False, bn=True, relu=False, dropout=False))

    # 32
    layer_idx += 1
    name = 'layer%d' % layer_idx
    nf = nf * 2
    main.add_module('%s.leakyrelu' % name, nn.LeakyReLU(0.2, inplace=True))
    main.add_module('%s.conv' % name, nn.Conv2d(nf, nf*2, 4, 1, 1, bias=False))
    main.add_module('%s.bn' % name, nn.BatchNorm2d(nf*2))

    # 31
    layer_idx += 1
    name = 'layer%d' % layer_idx
    nf = nf * 2
    main.add_module('%s.leakyrelu' % name, nn.LeakyReLU(0.2, inplace=True))
    main.add_module('%s.conv' % name, nn.Conv2d(nf, 1, 4, 1, 1, bias=False))
    main.add_module('%s.sigmoid' % name , nn.Sigmoid())
    # 30 (sizePatchGAN=30)

    self.main = main

  def forward(self, x):
    output = self.main(x)
    return output



class G(nn.Module):
  def __init__(self, input_nc, output_nc, nf):
    super(G, self).__init__()
    # input is 256 x 256
    layer_idx = 1
    name = 'layer%d' % layer_idx
    layer1 = nn.Sequential()
    layer1.add_module(name, nn.Conv2d(input_nc, nf, 4, 2, 1, bias=False))
    # input is 128 x 128
    layer_idx += 1
    name = 'layer%d' % layer_idx
    layer2 = blockUNet(nf, nf*2, name, transposed=False, bn=True, relu=False, dropout=False)
    # input is 64 x 64
    layer_idx += 1
    name = 'layer%d' % layer_idx
    layer3 = blockUNet(nf*2, nf*4, name, transposed=False, bn=True, relu=False, dropout=False)
    # input is 32
    layer_idx += 1
    name = 'layer%d' % layer_idx
    layer4 = blockUNet(nf*4, nf*8, name, transposed=False, bn=True, relu=False, dropout=False)
    # input is 16
    layer_idx += 1
    name = 'layer%d' % layer_idx
    layer5 = blockUNet(nf*8, nf*8, name, transposed=False, bn=True, relu=False, dropout=False)
    # input is 8
    layer_idx += 1
    name = 'layer%d' % layer_idx
    layer6 = blockUNet(nf*8, nf*8, name, transposed=False, bn=True, relu=False, dropout=False)
    # input is 4
    layer_idx += 1
    name = 'layer%d' % layer_idx
    layer7 = blockUNet(nf*8, nf*8, name, transposed=False, bn=True, relu=False, dropout=False)
    # input is 2 x  2
    layer_idx += 1
    name = 'layer%d' % layer_idx
    layer8 = blockUNet(nf*8, nf*8, name, transposed=False, bn=True, relu=False, dropout=False)

    ## NOTE: decoder
    # input is 1
    name = 'dlayer%d' % layer_idx
    d_inc = nf*8
    dlayer8 = blockUNet(d_inc, nf*8, name, transposed=True, bn=False, relu=True, dropout=True)

    # input is 2
    layer_idx -= 1
    name = 'dlayer%d' % layer_idx
    d_inc = nf*8*2
    dlayer7 = blockUNet(d_inc, nf*8, name, transposed=True, bn=True, relu=True, dropout=True)
    # input is 4
    layer_idx -= 1
    name = 'dlayer%d' % layer_idx
    d_inc = nf*8*2
    dlayer6 = blockUNet(d_inc, nf*8, name, transposed=True, bn=True, relu=True, dropout=True)
    # input is 8
    layer_idx -= 1
    name = 'dlayer%d' % layer_idx
    d_inc = nf*8*2
    dlayer5 = blockUNet(d_inc, nf*8, name, transposed=True, bn=True, relu=True, dropout=False)
    # input is 16
    layer_idx -= 1
    name = 'dlayer%d' % layer_idx
    d_inc = nf*8*2
    dlayer4 = blockUNet(d_inc, nf*4, name, transposed=True, bn=True, relu=True, dropout=False)
    # input is 32
    layer_idx -= 1
    name = 'dlayer%d' % layer_idx
    d_inc = nf*4*2
    dlayer3 = blockUNet(d_inc, nf*2, name, transposed=True, bn=True, relu=True, dropout=False)
    # input is 64
    layer_idx -= 1
    name = 'dlayer%d' % layer_idx
    d_inc = nf*2*2
    dlayer2 = blockUNet(d_inc, nf, name, transposed=True, bn=True, relu=True, dropout=False)
    # input is 128
    layer_idx -= 1
    name = 'dlayer%d' % layer_idx
    dlayer1 = nn.Sequential()
    d_inc = nf*2
    dlayer1.add_module('%s.relu' % name, nn.ReLU(inplace=True))
    dlayer1.add_module('%s.tconv' % name, nn.ConvTranspose2d(d_inc, 20, 4, 2, 1, bias=False))

    dlayerfinal = nn.Sequential()

    dlayerfinal.add_module('%s.conv' % name, nn.Conv2d(24, output_nc, 3, 1, 1, bias=False))
    dlayerfinal.add_module('%s.tanh' % name, nn.Tanh())

    self.conv1010 = nn.Conv2d(20, 1, kernel_size=1,stride=1,padding=0)  # 1mm
    self.conv1020 = nn.Conv2d(20, 1, kernel_size=1,stride=1,padding=0)  # 1mm
    self.conv1030 = nn.Conv2d(20, 1, kernel_size=1,stride=1,padding=0)  # 1mm
    self.conv1040 = nn.Conv2d(20, 1, kernel_size=1,stride=1,padding=0)  # 1mm

    self.refine3= nn.Conv2d(20+4, 3, kernel_size=3,stride=1,padding=1)

    self.upsample = F.upsample_nearest

    self.layer1 = layer1
    self.layer2 = layer2
    self.layer3 = layer3
    self.layer4 = layer4
    self.layer5 = layer5
    self.layer6 = layer6
    self.layer7 = layer7
    self.layer8 = layer8
    self.dlayer8 = dlayer8
    self.dlayer7 = dlayer7
    self.dlayer6 = dlayer6
    self.dlayer5 = dlayer5
    self.dlayer4 = dlayer4
    self.dlayer3 = dlayer3
    self.dlayer2 = dlayer2
    self.dlayer1 = dlayer1
    self.dlayerfinal = dlayerfinal
    self.relu=nn.LeakyReLU(0.2, inplace=True)

  def forward(self, x):
    out1 = self.layer1(x)
    out2 = self.layer2(out1)
    out3 = self.layer3(out2)
    out4 = self.layer4(out3)
    out5 = self.layer5(out4)
    out6 = self.layer6(out5)
    out7 = self.layer7(out6)
    out8 = self.layer8(out7)
    dout8 = self.dlayer8(out8)
    dout8_out7 = torch.cat([dout8, out7], 1)
    dout7 = self.dlayer7(dout8_out7)
    dout7_out6 = torch.cat([dout7, out6], 1)
    dout6 = self.dlayer6(dout7_out6)
    dout6_out5 = torch.cat([dout6, out5], 1)
    dout5 = self.dlayer5(dout6_out5)
    dout5_out4 = torch.cat([dout5, out4], 1)
    dout4 = self.dlayer4(dout5_out4)
    dout4_out3 = torch.cat([dout4, out3], 1)
    dout3 = self.dlayer3(dout4_out3)
    dout3_out2 = torch.cat([dout3, out2], 1)
    dout2 = self.dlayer2(dout3_out2)
    dout2_out1 = torch.cat([dout2, out1], 1)
    dout1 = self.dlayer1(dout2_out1)

    shape_out = dout1.data.size()
    # print(shape_out)
    shape_out = shape_out[2:4]

    x101 = F.avg_pool2d(dout1, 16)
    x102 = F.avg_pool2d(dout1, 8)
    x103 = F.avg_pool2d(dout1, 4)
    x104 = F.avg_pool2d(dout1, 2)

    x1010 = self.upsample(self.relu(self.conv1010(x101)),size=shape_out)
    x1020 = self.upsample(self.relu(self.conv1020(x102)),size=shape_out)
    x1030 = self.upsample(self.relu(self.conv1030(x103)),size=shape_out)
    x1040 = self.upsample(self.relu(self.conv1040(x104)),size=shape_out)

    dehaze = torch.cat((x1010, x1020, x1030, x1040, dout1), 1)

    dout1 = self.dlayerfinal(dehaze)

    return dout1

class G2(nn.Module):
  def __init__(self, input_nc, output_nc, nf):
    super(G2, self).__init__()
    # input is 256 x 256
    layer_idx = 1
    name = 'layer%d' % layer_idx
    layer1 = nn.Sequential()
    layer1.add_module(name, nn.Conv2d(input_nc, nf, 4, 2, 1, bias=False))
    # input is 128 x 128
    layer_idx += 1
    name = 'layer%d' % layer_idx
    layer2 = blockUNet(nf, nf*2, name, transposed=False, bn=True, relu=False, dropout=False)
    # input is 64 x 64
    layer_idx += 1
    name = 'layer%d' % layer_idx
    layer3 = blockUNet(nf*2, nf*4, name, transposed=False, bn=True, relu=False, dropout=False)
    # input is 32
    layer_idx += 1
    name = 'layer%d' % layer_idx
    layer4 = blockUNet(nf*4, nf*8, name, transposed=False, bn=True, relu=False, dropout=False)
    # input is 16
    layer_idx += 1
    name = 'layer%d' % layer_idx
    layer5 = blockUNet(nf*8, nf*8, name, transposed=False, bn=True, relu=False, dropout=False)
    # input is 8
    layer_idx += 1
    name = 'layer%d' % layer_idx
    layer6 = blockUNet(nf*8, nf*8, name, transposed=False, bn=True, relu=False, dropout=False)
    # input is 4
    layer_idx += 1
    name = 'layer%d' % layer_idx
    layer7 = blockUNet(nf*8, nf*8, name, transposed=False, bn=True, relu=False, dropout=False)
    # input is 2 x  2
    layer_idx += 1
    name = 'layer%d' % layer_idx
    layer8 = blockUNet(nf*8, nf*8, name, transposed=False, bn=True, relu=False, dropout=False)

    ## NOTE: decoder
    # input is 1
    name = 'dlayer%d' % layer_idx
    d_inc = nf*8
    dlayer8 = blockUNet(d_inc, nf*8, name, transposed=True, bn=False, relu=True, dropout=True)

    #import pdb; pdb.set_trace()
    # input is 2
    layer_idx -= 1
    name = 'dlayer%d' % layer_idx
    d_inc = nf*8*2
    dlayer7 = blockUNet(d_inc, nf*8, name, transposed=True, bn=True, relu=True, dropout=True)
    # input is 4
    layer_idx -= 1
    name = 'dlayer%d' % layer_idx
    d_inc = nf*8*2
    dlayer6 = blockUNet(d_inc, nf*8, name, transposed=True, bn=True, relu=True, dropout=True)
    # input is 8
    layer_idx -= 1
    name = 'dlayer%d' % layer_idx
    d_inc = nf*8*2
    dlayer5 = blockUNet(d_inc, nf*8, name, transposed=True, bn=True, relu=True, dropout=False)
    # input is 16
    layer_idx -= 1
    name = 'dlayer%d' % layer_idx
    d_inc = nf*8*2
    dlayer4 = blockUNet(d_inc, nf*4, name, transposed=True, bn=True, relu=True, dropout=False)
    # input is 32
    layer_idx -= 1
    name = 'dlayer%d' % layer_idx
    d_inc = nf*4*2
    dlayer3 = blockUNet(d_inc, nf*2, name, transposed=True, bn=True, relu=True, dropout=False)
    # input is 64
    layer_idx -= 1
    name = 'dlayer%d' % layer_idx
    d_inc = nf*2*2
    dlayer2 = blockUNet(d_inc, nf, name, transposed=True, bn=True, relu=True, dropout=False)
    # input is 128
    layer_idx -= 1
    name = 'dlayer%d' % layer_idx
    dlayer1 = nn.Sequential()
    d_inc = nf*2
    dlayer1.add_module('%s.relu' % name, nn.ReLU(inplace=True))
    dlayer1.add_module('%s.tconv' % name, nn.ConvTranspose2d(d_inc, output_nc, 4, 2, 1, bias=False))
    dlayer1.add_module('%s.tanh' % name, nn.LeakyReLU(0.2, inplace=True))

    self.layer1 = layer1
    self.layer2 = layer2
    self.layer3 = layer3
    self.layer4 = layer4
    self.layer5 = layer5
    self.layer6 = layer6
    self.layer7 = layer7
    self.layer8 = layer8
    self.dlayer8 = dlayer8
    self.dlayer7 = dlayer7
    self.dlayer6 = dlayer6
    self.dlayer5 = dlayer5
    self.dlayer4 = dlayer4
    self.dlayer3 = dlayer3
    self.dlayer2 = dlayer2
    self.dlayer1 = dlayer1

  def forward(self, x):
    out1 = self.layer1(x)
    out2 = self.layer2(out1)
    out3 = self.layer3(out2)
    out4 = self.layer4(out3)
    out5 = self.layer5(out4)
    out6 = self.layer6(out5)
    out7 = self.layer7(out6)
    out8 = self.layer8(out7)
    dout8 = self.dlayer8(out8)
    dout8_out7 = torch.cat([dout8, out7], 1)
    dout7 = self.dlayer7(dout8_out7)
    dout7_out6 = torch.cat([dout7, out6], 1)
    dout6 = self.dlayer6(dout7_out6)
    dout6_out5 = torch.cat([dout6, out5], 1)
    dout5 = self.dlayer5(dout6_out5)
    dout5_out4 = torch.cat([dout5, out4], 1)
    dout4 = self.dlayer4(dout5_out4)
    dout4_out3 = torch.cat([dout4, out3], 1)
    dout3 = self.dlayer3(dout4_out3)
    dout3_out2 = torch.cat([dout3, out2], 1)
    dout2 = self.dlayer2(dout3_out2)
    dout2_out1 = torch.cat([dout2, out1], 1)
    dout1 = self.dlayer1(dout2_out1)
    return dout1


class BottleneckBlock(nn.Module):
    def __init__(self, in_planes, out_planes, dropRate=0.0):
        super(BottleneckBlock, self).__init__()
        inter_planes = out_planes * 4
        self.bn1 = nn.BatchNorm2d(in_planes)
        self.relu = nn.ReLU(inplace=True)
        self.conv1 = nn.Conv2d(in_planes, inter_planes, kernel_size=1, stride=1,
                               padding=0, bias=False)
        self.bn2 = nn.BatchNorm2d(inter_planes)
        self.conv2 = nn.Conv2d(inter_planes, out_planes, kernel_size=3, stride=1,
                               padding=1, bias=False)
        self.droprate = dropRate
    def forward(self, x):
        out = self.conv1(self.relu(self.bn1(x)))
        if self.droprate > 0:
            out = F.dropout(out, p=self.droprate, inplace=False, training=self.training)
        out = self.conv2(self.relu(self.bn2(out)))
        if self.droprate > 0:
            out = F.dropout(out, p=self.droprate, inplace=False, training=self.training)
        return torch.cat([x, out], 1)

class TransitionBlock(nn.Module):
    def __init__(self, in_planes, out_planes, dropRate=0.0):
        super(TransitionBlock, self).__init__()
        self.bn1 = nn.BatchNorm2d(in_planes)
        self.relu = nn.ReLU(inplace=True)
        self.conv1 = nn.ConvTranspose2d(in_planes, out_planes, kernel_size=1, stride=1,
                               padding=0, bias=False)
        self.droprate = dropRate
    def forward(self, x):
        out = self.conv1(self.relu(self.bn1(x)))
        if self.droprate > 0:
            out = F.dropout(out, p=self.droprate, inplace=False, training=self.training)
        return F.upsample_nearest(out, scale_factor=2)






class Dense(nn.Module):
    def __init__(self):
        super(Dense, self).__init__()




        ############# 256-256  ##############
        haze_class = models.densenet121(pretrained=True)

        self.conv0=haze_class.features.conv0
        self.norm0=haze_class.features.norm0
        self.relu0=haze_class.features.relu0
        self.pool0=haze_class.features.pool0

        ############# Block1-down 64-64  ##############
        self.dense_block1=haze_class.features.denseblock1
        self.trans_block1=haze_class.features.transition1

        ############# Block2-down 32-32  ##############
        self.dense_block2=haze_class.features.denseblock2
        self.trans_block2=haze_class.features.transition2

        ############# Block3-down  16-16 ##############
        self.dense_block3=haze_class.features.denseblock3
        self.trans_block3=haze_class.features.transition3

        ############# Block4-up  8-8  ##############
        self.dense_block4=BottleneckBlock(512,256)
        self.trans_block4=TransitionBlock(768,128)

        ############# Block5-up  16-16 ##############
        self.dense_block5=BottleneckBlock(384,256)
        self.trans_block5=TransitionBlock(640,128)

        ############# Block6-up 32-32   ##############
        self.dense_block6=BottleneckBlock(256,128)
        self.trans_block6=TransitionBlock(384,64)


        ############# Block7-up 64-64   ##############
        self.dense_block7=BottleneckBlock(64,64)
        self.trans_block7=TransitionBlock(128,32)

        ## 128 X  128
        ############# Block8-up c  ##############
        self.dense_block8=BottleneckBlock(32,32)
        self.trans_block8=TransitionBlock(64,16)

        self.conv_refin=nn.Conv2d(19,20,3,1,1)
        self.tanh=nn.Tanh()


        self.conv1010 = nn.Conv2d(20, 1, kernel_size=1,stride=1,padding=0)  # 1mm
        self.conv1020 = nn.Conv2d(20, 1, kernel_size=1,stride=1,padding=0)  # 1mm
        self.conv1030 = nn.Conv2d(20, 1, kernel_size=1,stride=1,padding=0)  # 1mm
        self.conv1040 = nn.Conv2d(20, 1, kernel_size=1,stride=1,padding=0)  # 1mm

        self.refine3= nn.Conv2d(20+4, 3, kernel_size=3,stride=1,padding=1)
        # self.refine3= nn.Conv2d(20+4, 3, kernel_size=7,stride=1,padding=3)

        self.upsample = F.upsample_nearest

        self.relu=nn.LeakyReLU(0.2, inplace=True)

    def forward(self, x):
        ## 256x256
        x0=self.pool0(self.relu0(self.norm0(self.conv0(x))))

        ## 64 X 64
        x1=self.dense_block1(x0)
        # print x1.size()
        x1=self.trans_block1(x1)

        ###  32x32
        x2=self.trans_block2(self.dense_block2(x1))
        # print  x2.size()


        ### 16 X 16
        x3=self.trans_block3(self.dense_block3(x2))

        # x3=Variable(x3.data,requires_grad=True)

        ## 8 X 8
        x4=self.trans_block4(self.dense_block4(x3))

        x42=torch.cat([x4,x2],1)
        ## 16 X 16
        x5=self.trans_block5(self.dense_block5(x42))

        x52=torch.cat([x5,x1],1)
        ##  32 X 32
        x6=self.trans_block6(self.dense_block6(x52))

        ##  64 X 64
        x7=self.trans_block7(self.dense_block7(x6))

        ##  128 X 128
        x8=self.trans_block8(self.dense_block8(x7))

        # print x8.size()
        # print x.size()

        x8=torch.cat([x8,x],1)

        # print x8.size()

        x9=self.relu(self.conv_refin(x8))

        shape_out = x9.data.size()
        # print(shape_out)
        shape_out = shape_out[2:4]

        x101 = F.avg_pool2d(x9, 32)
        x102 = F.avg_pool2d(x9, 16)
        x103 = F.avg_pool2d(x9, 8)
        x104 = F.avg_pool2d(x9, 4)

        x1010 = self.upsample(self.relu(self.conv1010(x101)), size=shape_out)
        x1020 = self.upsample(self.relu(self.conv1020(x102)), size=shape_out)
        x1030 = self.upsample(self.relu(self.conv1030(x103)), size=shape_out)
        x1040 = self.upsample(self.relu(self.conv1040(x104)), size=shape_out)

        dehaze = torch.cat((x1010, x1020, x1030, x1040, x9), 1)
        dehaze = self.tanh(self.refine3(dehaze))

        return dehaze



class dehaze(nn.Module):
  def __init__(self, input_nc, output_nc, nf):
    super(dehaze, self).__init__()
    self.tran_est=G(input_nc=3,output_nc=3, nf=64)
    self.atp_est=G2(input_nc=3,output_nc=3, nf=8)

    self.tran_dense=Dense()
    self.relu=nn.LeakyReLU(0.2, inplace=True)
    # self.relu5=nn.ReLU6()

    self.tanh=nn.Tanh()

    self.refine1= nn.Conv2d(6, 20, kernel_size=3,stride=1,padding=1)
    self.refine2= nn.Conv2d(20, 20, kernel_size=3,stride=1,padding=1)
    self.threshold=nn.Threshold(0.1, 0.1)

    self.conv1010 = nn.Conv2d(20, 1, kernel_size=1,stride=1,padding=0)  # 1mm
    self.conv1020 = nn.Conv2d(20, 1, kernel_size=1,stride=1,padding=0)  # 1mm
    self.conv1030 = nn.Conv2d(20, 1, kernel_size=1,stride=1,padding=0)  # 1mm
    self.conv1040 = nn.Conv2d(20, 1, kernel_size=1,stride=1,padding=0)  # 1mm

    self.refine3= nn.Conv2d(20+4, 3, kernel_size=3,stride=1,padding=1)

    self.upsample = F.upsample_nearest

    self.batch1= nn.BatchNorm2d(20)

    # self.batch2 = nn.InstanceNorm2d(100, affine=True)
  def forward(self, x):


    tran=self.tran_dense(x)
    atp= self.atp_est(x)


    # x = Variable(x.data, requires_grad=True)

    # zz= torch.abs(self.threshold(tran))
    zz= torch.abs((tran))+(10**-10)
    shape_out1 = atp.data.size()
    # print(shape_out)
    # shape_out = shape_out[0:5]

    # atp_mean=torch.mean(atp)

    # threshold = nn.Threshold(10, 0.95)

    shape_out = shape_out1[2:4]
    atp = F.avg_pool2d(atp, shape_out1[2])
    atp = self.upsample(self.relu(atp),size=shape_out)


    # print atp.data
    # atp = threshold(atp)



    dehaze= (x-atp)/zz+ atp
    dehaze2=dehaze


    dehaze=torch.cat([dehaze,x],1)
    # dehaze=dehaze/(tran+(10**-10))
    # dehaze=self.relu(self.batch1(self.refine1(dehaze)))
    # dehaze=self.relu(self.batch1(self.refine2(dehaze)))

    dehaze=self.relu((self.refine1(dehaze)))
    dehaze=self.relu((self.refine2(dehaze)))
    shape_out = dehaze.data.size()
    # print(shape_out)
    shape_out = shape_out[2:4]

    x101 = F.avg_pool2d(dehaze, 32)
    x1010 = F.avg_pool2d(dehaze, 32)

    x102 = F.avg_pool2d(dehaze, 16)
    x1020 = F.avg_pool2d(dehaze, 16)

    x103 = F.avg_pool2d(dehaze, 8)

    x104 = F.avg_pool2d(dehaze, 4)


    x1010 = self.upsample(self.relu(self.conv1010(x101)),size=shape_out)
    x1020 = self.upsample(self.relu(self.conv1020(x102)),size=shape_out)
    x1030 = self.upsample(self.relu(self.conv1030(x103)),size=shape_out)
    x1040 = self.upsample(self.relu(self.conv1040(x104)),size=shape_out)

    dehaze = torch.cat((x1010, x1020, x1030, x1040, dehaze), 1)
    dehaze= self.tanh(self.refine3(dehaze))

    return dehaze, tran, atp, dehaze2

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【使用教程】CANopen一体化伺服电机在汇川H5U PLC上的应用(上)

本文内容主要介绍了立迈胜一体化低压伺服CANopen通信的电机在汇川H5UPLC上的使用,本篇主要讲解环境的搭建以及软件自带的调试功能使电机运动起来。 一、系统构成 本系统主要构成是笔记本电脑、汇川PLC(H5U-1614MTD-A8)、PMM60系列一体化伺服电机(PMM6040B-CANopen)…

Maxon One 春季版本更新动态

2023年3月29日,Maxon,为剪辑师、电影制作人、动态设计师、视觉特效艺术家和各类创作者提供专业软件解决方案的开发商,今天宣布对Maxon One进行全面更新。 Maxon的2023年春季版本在整个产品系列中提供了令人振奋的新功能和工作流程改进&#x…

创略科技联合创始人兼总裁杨辰韵:AIGC、隐私计算赋能数字营销的本质是“以客户为中心”丨数据猿专访...

‍数据智能产业创新服务媒体——聚焦数智 改变商业MarTech概念现身已超十年,伴随着企业数字化转型的大背景,中国MarTech市场也迎来了高速发展。据《2022年中国MarTech市场洞察报告》数据显示,2017-2021年,中国 MarTech产业规模从…

windows服务器自带IIS搭建网站并发布公网访问【内网穿透】

文章目录1.前言2.Windows网页设置2.1 Windows IIS功能设置2.2 IIS网页访问测试3. Cpolar内网穿透3.1 下载安装Cpolar3.2 Cpolar云端设置3.3 Cpolar本地设置4.公网访问测试5.结语转载自远程源码文章:【IIS搭建网站】本地电脑做服务器搭建web站点并公网访问「内网穿透…

普通人是否能从ChatGPT中分一杯羹?

ChatGPT3.0刚刚推出,最开始的时候,人们只是将ChatGPT看作一个很会聊天的机器人,无论问题多么天马行空,它的答案看上去都有理有据。后来,像打开潘多拉魔盒一样,很多人开始拿它编大纲、撰写文案、编代码、创作…

Apache 配置与应用

目录构建虚拟 Web 主机基于域名的虚拟主机1.为虚拟主机提供域名解析2.为虚拟主机准备网页文档3.添加虚拟主机配置4.设置访问控制5.加载独立的配置文件6.在客户机中访问虚拟 Web 主机基于IP地址的虚拟主机基于端口的虚拟主机Apache 连接保持构建Web虚拟目录与用户授权…

Sequence(二分 + 线段树)

H-Sequence_2020ICPC 江西省大学生程序设计竞赛(重现赛)Joanh_Lan (nowcoder.com) 题目描述 给定一个包含n个整数的数组a,你要对它执行两种类型的m个操作。1.给定两个整数x,y,将索引x的个数替换为数字y,即ax:y。2.给定…

【软考五】数据库(做题)

该文章不适合学习数据库,适合考证,遇到实际问题的,不要在这儿浪费时间。切记切记 软考之数据库一、概念数据模型(下午题常考)二、结构数据模型关系模型1、关系模型中基本术语2、关系模型中的关系完整性约束3、关系代数…

蓝桥杯 回忆迷宫 BFS DFS暴力模拟

⭐ 题目地址 样例输入 17 UUUULLLLDDDDRRRRU样例输出 ***** * * * *** * * *** * * *** * * ******🤠 注意方向:颠倒数组,行下标 是 y,列下标 是 x import java.util.*;public class Main { static int n;static int …

如何用jmeter+ant+jenkins搭建一个接口自动化测试框架?

目录 前言 一、什么是Jmeter? 二、什么是Ant? 三、什么是Jenkins? 四、如何构建一个JmeterAntJenkins的接口自动化测试框架? 五、JmeterAntJenkins接口自动化测试框架的优势和特点 六、总结 前言 Jmeter是一款功能强大的开…

2023年Win11备份文件的快捷方式

文件备份对于数据保护非常重要。无论是什么类型的文件,如照片、文档、音频、视频,它们对您来说都是独一无二的、珍贵的,因此您想备份文件并保护它们。 首先,备份文件无疑是保护文件的好习惯,尤其是定时备份。其次&…

笔记本可自行更换CPU、独显了,老外用它手搓了台“PS5”

前面说到微软打算在 Win12 出来前搞出个模块化的Windows:下一个系统不是Win12,微软要复活Win10X。 模块化不用小蝾再过多介绍了,就像积木一样拼在一起组成一个整体。 优势就很明显了,由于每个部分都是单独的模块,更新…

ChatGPT如何写作-怎么让chatGPT批量写作

ChatGPT如何写作 使用 ChatGPT 进行写作一般可以遵循以下步骤: 定义写作主题和目的。确定写作主题和目的,包括要解决的问题、目标读者群体以及需要涵盖的主要内容。 收集文献和资料。收集与主题相关的文献和资料,可以从互联网、书籍、报刊杂…

Spring Cloud组件源码之OpenFeign源码分析

" Spring 到底是春天的来临万物复苏,还是春转夏的干燥又炎热呢?" Spring的来临让JavaEE走向了另一个高度。便捷的开发,完美的生态。物极必反,学习Spring的成本越来越低,导致Java程序员越来越密集&#xff0…

VS2022编译libui库

libui是一个 C 中简单且可移植(但并非不灵活)的 GUI 库,它使用每个平台原生的GUI技术进行绘制。 官网地址:链接 本文将使用VS2022编译libui库,操作系统为Windows10。 1. 下载源代码 首先在官网下载源代码,由于此代码不依赖第三库,故只需下载源代码即可进行编译。 我下…

JavaScript函数中的arguments(js函数中的arguments,函数默认参数arguments)

简述:js中的函数大家都比较熟悉,今天来分享下函数中的默认参数arguments。js的函数参数和其他的语言有些不同,它并不介意你传进来多少个参数,以及参数的数据类型,即使你在定义函数时,只设置了两个形参&…

「解析」Matplotlib 绘制折线图

相比于【优雅】matplotlib 常见图、【优雅】matplotlib 3D图 而言,折线图使用的频率会更高一些,在此整理下最近使用 Matplotlib 绘制折线图常用的一些配置,小伙伴们只需要修改对应的 aug_list、list 即可直接使用 # !/usr/bin/env python …

asp.net mvc学习(三)

Razor语法 Razor语法特点 结构性强,容易阅读。易于学习。不是新的语言。在任何编辑器上编写Razor都很容易。与ide充分结合。 Razor语法主要规则 Razor代码封装于{...}中。 行内表达式(变量和函数)以开头 代码语句以分号结尾 字符串由引号…

Python 进阶指南(编程轻松进阶):八、常见的 Python 陷阱

原文:http://inventwithpython.com/beyond/chapter8.html 虽然 Python 是我最喜欢的编程语言,但它也不是没有缺陷。每种语言都有缺点(有些比其他的多),Python 也不例外。新的 Python 程序员必须学会避免一些常见的“陷…

JavaScript 中问号的三种用法 ??和?.以及?: 您知道吗?

最近看了一些关于JavaScript的测试脚本,觉得JS 中问号的用法还是蛮有意思的,于是做了一下总结,在这里分享给大家!JS中的问号大概有三种用法,分别是:空值合并操作符、可选链操作符和三目运算。 问号问号&…