**

Python图像去雾

**
引言: 在过去的几十年中,单图像去雾作为基本的低级视觉任务已引起了计算机视觉社区和人工智能公司的越来越多的关注。其中最为典型的便是北大&北航提出FFA-Net去雾新网络和何凯明博士提出的暗通道去雾算法,现所有源码已开源。其论文链接:https://arxiv.org/abs/1911.07559。
而今天我们就将针对这两个项目进行实践。其中得到的去雾效果如下:

一、实验前的准备:
首先我们使用的python版本是3.6.5所用到的模块如下:
Pytorch模块用来模型训练和网络层建立;其底层和Torch框架一样,但是使用Python重新写了很多内容,不仅更加灵活,支持动态图,而且提供了Python接口。不仅能够实现强大的GPU加速,同时还支持动态神经网络。
numpy模块用来进行数值运算处理矩阵运算;
OpenCV用来读取图片和图像处理;
os模块用来读取数据集等本地文件操作。
二、FFA去雾算法
其代码结构如下图可见:

FFA-Net体系结构包含三个关键组件:
1.考虑到不同的通道特征包含完全不同的加权信息并且不同图像像素上的雾度分布不均匀,一种新颖的特征注意(FA)模块将通道注意与像素注意机制结合在一起。FA不平等地对待不同的特征和像素,这在处理不同类型的信息时提供了额外的灵活性,从而扩展了CNN的表示能力。
2.基本的块结构包括本地残差学习和功能注意,本地残差学习允许较不重要的信息(例如薄雾区域或低频)通过多个本地残差连接被绕开,让主网络体系结构专注于更有效的信息。
3.基于注意力的不同级别特征融合(FFA)结构,可从特征注意(FA)模块中自适应学习特征权重,从而为重要特征赋予更多权重。这种结构还可以保留浅层信息,并将其传递到深层。
实验结果表明,提出的FFANet在数量和质量上都大大超过了现有的单图像去雾方法,从而将SOTS室内测试数据集上最佳的PSNR度量从30.23db提高到35.77db。

其中训练FFA模型的部分代码如下:

def 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 PALayer(nn.Module):def __init__(self, channel):super(PALayer, self).__init__()self.pa = nn.Sequential(nn.Conv2d(channel, channel // 8, 1, padding=0, bias=True),nn.ReLU(inplace=True),nn.Conv2d(channel // 8, 1, 1, padding=0, bias=True),nn.Sigmoid())def forward(self, x):y = self.pa(x)return x * y
class CALayer(nn.Module):def __init__(self, channel):super(CALayer, self).__init__()self.avg_pool = nn.AdaptiveAvgPool2d(1)self.ca = nn.Sequential(nn.Conv2d(channel, channel // 8, 1, padding=0, bias=True),nn.ReLU(inplace=True),nn.Conv2d(channel // 8, channel, 1, padding=0, bias=True),nn.Sigmoid())def forward(self, x):y = self.avg_pool(x)y = self.ca(y)return x * y
class Block(nn.Module):def __init__(self, conv, dim, kernel_size,):super(Block, self).__init__()self.conv1=conv(dim, dim, kernel_size, bias=True)self.act1=nn.ReLU(inplace=True)self.conv2=conv(dim,dim,kernel_size,bias=True)self.calayer=CALayer(dim)self.palayer=PALayer(dim)def forward(self, x):res=self.act1(self.conv1(x))res=res+x res=self.conv2(res)res=self.calayer(res)res=self.palayer(res)res += x return res
class Group(nn.Module):def __init__(self, conv, dim, kernel_size, blocks):super(Group, self).__init__()modules = [ Block(conv, dim, kernel_size)  for _ in range(blocks)]modules.append(conv(dim, dim, kernel_size))self.gp = nn.Sequential(*modules)def forward(self, x):res = self.gp(x)res += xreturn res
class FFA(nn.Module):def __init__(self,gps,blocks,conv=default_conv):super(FFA, self).__init__()self.gps=gpsself.dim=64kernel_size=3pre_process = [conv(3, self.dim, kernel_size)]assert self.gps==3self.g1= Group(conv, self.dim, kernel_size,blocks=blocks)self.g2= Group(conv, self.dim, kernel_size,blocks=blocks)self.g3= Group(conv, self.dim, kernel_size,blocks=blocks)self.ca=nn.Sequential(*[nn.AdaptiveAvgPool2d(1),nn.Conv2d(self.dim*self.gps,self.dim//16,1,padding=0),nn.ReLU(inplace=True),nn.Conv2d(self.dim//16, self.dim*self.gps, 1, padding=0, bias=True),nn.Sigmoid()])self.palayer=PALayer(self.dim)post_precess = [conv(self.dim, self.dim, kernel_size),conv(self.dim, 3, kernel_size)]self.pre = nn.Sequential(*pre_process)self.post = nn.Sequential(*post_precess)def forward(self, x1):x = self.pre(x1)res1=self.g1(x)res2=self.g2(res1)res3=self.g3(res2)w=self.ca(torch.cat([res1,res2,res3],dim=1))w=w.view(-1,self.gps,self.dim)[:,:,:,None,None]out=w[:,0,::]*res1+w[:,1,::]*res2+w[:,2,::]*res3out=self.palayer(out)x=self.post(out)return x + x1

使用“python main.py --net=‘ffa’ --crop --crop_size=240 --blocks=19 --gps=3 --bs=2 --lr=0.0001 --trainset=‘its_train’ --testset=‘its_test’ --steps=500000 --eval_step=5000”命令实现模型的训练功能。
使用“python test.py --task=‘its or ots’ --test_imgs=‘test_imgs’”来测试模型效果:
最终得到效果如下:

三、暗通道去雾算法搭建
何恺明的暗通道先验(dark channel prior)去雾算法是CV界去雾领域很有名的算法,关于该算法的论文"Single Image Haze Removal Using Dark Channel Prior"一举获得2009年CVPR最佳论文。作者统计了大量的无雾图像,发现一条规律:每一幅图像的每一个像素的RGB三个颜色通道中,总有一个通道的灰度值很低。基于这个几乎可以视作是定理的先验知识,作者提出暗通道先验的去雾算法。
对于任意一幅输入图像,定义其暗通道的数学表达式为:

文章中介绍的方法是软抠图的方法,此方法过程复杂,速度缓慢,因此采用导向滤波对传输函数进行滤波。导向滤波的原理此处不再赘述,其伪代码为:

1、滤波函数:
定义最小值滤波函数:

def zmMinFilterGray(src, r=7):'''if r <= 0:return srch, w = src.shape[:2]I = srcres = np.minimum(I  , I[[0]+range(h-1)  , :])res = np.minimum(res, I[range(1,h)+[h-1], :])I = resres = np.minimum(I  , I[:, [0]+range(w-1)])res = np.minimum(res, I[:, range(1,w)+[w-1]])return zmMinFilterGray(res, r-1)'''return cv2.erode(src, np.ones((2*r+1, 2*r+1)))

引导滤波函数的实现:

def guidedfilter(I, p, r, eps):'''引导滤波,直接参考网上的matlab代码'''height, width = I.shapem_I = cv2.boxFilter(I, -1, (r,r))m_p = cv2.boxFilter(p, -1, (r,r))m_Ip = cv2.boxFilter(I*p, -1, (r,r))cov_Ip = m_Ip-m_I*m_pm_II = cv2.boxFilter(I*I, -1, (r,r))var_I = m_II-m_I*m_Ia = cov_Ip/(var_I+eps)b = m_p-a*m_Im_a = cv2.boxFilter(a, -1, (r,r))m_b = cv2.boxFilter(b, -1, (r,r))return m_a*I+m_b

计算大气遮罩图像V1和光照值A, V1 = 1-t/A

def getV1(m, r, eps, w, maxV1):  #输入rgb图像,值范围[0,1]'''计算大气遮罩图像V1和光照值A, V1 = 1-t/A'''V1 = np.min(m,2)                                         #得到暗通道图像V1 = guidedfilter(V1, zmMinFilterGray(V1,7), r, eps)     #使用引导滤波优化bins = 2000ht = np.histogram(V1, bins)                              #计算大气光照Ad = np.cumsum(ht[0])/float(V1.size)for lmax in range(bins-1, 0, -1):if d[lmax]<=0.999:breakA  = np.mean(m,2)[V1>=ht[1][lmax]].max()V1 = np.minimum(V1*w, maxV1)                   #对值范围进行限制return V1,A

得到的运行程序结果如下:

通过调整代码,将视频分帧,可以达到视频去雾的效果:
其完整代码如下:

import cv2
import numpy as np
def zmMinFilterGray(src, r=7):'''最小值滤波,r是滤波器半径''''''if r <= 0:return srch, w = src.shape[:2]I = srcres = np.minimum(I  , I[[0]+range(h-1)  , :])res = np.minimum(res, I[range(1,h)+[h-1], :])I = resres = np.minimum(I  , I[:, [0]+range(w-1)])res = np.minimum(res, I[:, range(1,w)+[w-1]])return zmMinFilterGray(res, r-1)'''return cv2.erode(src, np.ones((2 * r + 1, 2 * r + 1)))  # 使用opencv的erode函数更高效
def guidedfilter(I, p, r, eps):'''引导滤波'''height, width = I.shapem_I = cv2.boxFilter(I, -1, (r, r))m_p = cv2.boxFilter(p, -1, (r, r))m_Ip = cv2.boxFilter(I * p, -1, (r, r))cov_Ip = m_Ip - m_I * m_pm_II = cv2.boxFilter(I * I, -1, (r, r))var_I = m_II - m_I * m_Ia = cov_Ip / (var_I + eps)b = m_p - a * m_Im_a = cv2.boxFilter(a, -1, (r, r))m_b = cv2.boxFilter(b, -1, (r, r))return m_a * I + m_b
def getV1(m, r, eps, w, maxV1):  # 输入rgb图像,值范围[0,1]'''计算大气遮罩图像V1和光照值A, V1 = 1-t/A'''V1 = np.min(m, 2)  # 得到暗通道图像V1 = guidedfilter(V1, zmMinFilterGray(V1, 7), r, eps)  # 使用引导滤波优化bins = 2000ht = np.histogram(V1, bins)  # 计算大气光照Ad = np.cumsum(ht[0]) / float(V1.size)for lmax in range(bins - 1, 0, -1):if d[lmax] <= 0.999:breakA = np.mean(m, 2)[V1 >= ht[1][lmax]].max()V1 = np.minimum(V1 * w, maxV1)  # 对值范围进行限制return V1, A
def deHaze(m, r=81, eps=0.001, w=0.95, maxV1=0.80, bGamma=False):Y = np.zeros(m.shape)V1, A = getV1(m, r, eps, w, maxV1)  # 得到遮罩图像和大气光照for k in range(3):Y[:, :, k] = (m[:, :, k] - V1) / (1 - V1 / A)  # 颜色校正Y = np.clip(Y, 0, 1)if bGamma:Y = Y ** (np.log(0.5) / np.log(Y.mean()))  # gamma校正,默认不进行该操作return Y
video = "1.mp4"
cap = cv2.VideoCapture(video)
while cap.isOpened():_,frame = cap.read()frame = cv2.flip(frame, -180)cv2.imwrite("temp.jpg",frame)m = deHaze(frame / 255.0) * 255height, width = m.shape[:2]# 缩小图像size = (int(width * 0.5), int(height * 0.5))shrink = cv2.resize(m, size, interpolation=cv2.INTER_AREA)cv2.imwrite('defog.jpg', shrink)img = cv2.imread("defog.jpg")cv2.imshow("frame",img)key = cv2.waitKey(1) & 0xFFif key == ord("q"):break
cap.release()
cv2.destroyAllWindows()

****源码GitHub地址:https://github.com/zhilin007/FFA-Net
欢迎大家关注公众号:

Python图像去雾相关推荐

  1. python图像去雾算法实现

    Kaiming早在09年以MSRA实习生的身份获得CVPR best paper,其成果就是给图像去雾.当时并没有用深度学习,却能实现让人震惊的效果. 先看下效果: 左边是原图,右边是去雾霾之后的图. ...

  2. python图像去污_python图像去雾总结

    本人qq号:226607573,欢迎互相讨论的伙伴们 毕设期间对python图像去雾的学习与总结 近年来,雾霾越来越严重,导致户外获取的图像严重退化,何如将户外获取的有雾图像复原成高质量的清晰图像,已 ...

  3. [Python图像识别] 四十六.图像预处理之图像去雾详解(ACE算法和暗通道先验去雾算法)

    该系列文章是讲解Python OpenCV图像处理知识,前期主要讲解图像入门.OpenCV基础用法,中期讲解图像处理的各种算法,包括图像锐化算子.图像增强技术.图像分割等,后期结合深度学习研究图像识别 ...

  4. Python暗通道图像去雾

    何凯明的经典图像去雾算法,直接上代码啦,理论后续讲解哈~ Python代码如下: #!/usr/bin/env python # -*- coding: utf-8 -*- from PIL impo ...

  5. Python基于OpenCV的图像去雾算法[完整源码&部署教程]

    1.图片识别 2.视频展示 [项目分享]Python基于OpenCV的图像去雾算法[完整源码&部署教程]_哔哩哔哩_bilibili 3.算法原理 图像增强算法常见于对图像的亮度.对比度.饱和 ...

  6. python:实现图像去雾算法(附完整源码)

    python:实现图像去雾算法 import cv2import mathimport numpy as npdef DarkChannel(im,sz):b,g,r = cv2.split(im)d ...

  7. python图像去污_百度AI攻略:图像去雾

    图像去雾:对浓雾天气下拍摄,导致细节无法辨认的图像进行去雾处理,还原更清晰真实的图像 调用攻略(Python3) 首先认证授权: 在开始调用任何API之前需要先进行认证授权,具体的说明请参考: 获取A ...

  8. python关于图像去雾

    关于图像去雾的一些资料汇总 这学期的图像处理期末大作业选题为图像去雾,在完成时搜集了大量的资料和代码参考,在此做个汇集,也算是一个回顾. 初期准备 首先是对图像去雾的一个大致的了解,是在知乎上看的一篇 ...

  9. 图像去雾/图像去雨(matlab/python)

    看到许多小伙伴想进行图像去雨,图像去雾的任务,由于以前进行了此类项目,所以在此书写博客进行交流. 代码获取 去雨前言 从静止图像中去除雨水是一项复杂且具有挑战性的任务.雨滴仅影响图像的很小区域,因此导 ...

最新文章

  1. mysql统计出每个姓氏的人数_你见过什么偏僻的姓氏?明明是老虎的虎姓氏却读māo...
  2. 调用实现天气预报功能android,Android编程实现获取新浪天气预报数据的方法
  3. 显示部分数据标签_长春市农贸市场监测数据显示:粮油和水果价格平稳,部分副食品价格小幅波动...
  4. js中两个对象的比较
  5. python类的应用_Python · 元类(Meta Class)及其应用
  6. 番茄时间有感之关于在疫情期间我与ACM不得不说的故事
  7. 从C源代码到可执行文件的四个过程:预处理、编译、汇编、链接
  8. Qt工作笔记-QTableWidget设置委托(使用QStyledItemDelegate画3只小猪)
  9. 2DASL:目前最好的开源人脸3D重建与密集对齐算法
  10. (44)System Verilog数组逻辑运算
  11. python删除第一行_python3.7 openpyxl 删除指定一列或者一行的代码
  12. [转载] 2011 ScrumGathering大会简要记录 - 周金根
  13. Nas初体验(黑群晖实战)
  14. latex 数学公式_推荐一款编写数学公式的国产神器:AxMath,可与LATEX双向转换
  15. acwing每日一题-战舰
  16. 我有阳光(我爱生活)
  17. PocketPC中汉字输入法分析与实现(…
  18. 深圳外包及不考虑公司名单
  19. Android如何定制主题
  20. 安卓模拟器登录微信自动化测试最佳实践

热门文章

  1. linux服务端查看firebox版本,[图]Linux端Firefox 84将默认启用WebRender
  2. 精准送达目标客户——基于极光平台优化Android通知
  3. SAP中WM仓库管理中关于仓储单位SU的应用理解
  4. python申明变量注意事项_python申明变量
  5. echarts3d地图 使用scatter3D散点部分数据陷进地图中
  6. 二三四五再被监管点名:弹窗过多过频过大,上半年业绩下滑约七成
  7. 思科---北京某销售公司真实网络环境拓扑(图多杀猫)
  8. 【C#】获取汉字拼音首字母和全拼
  9. 江苏省高中计算机课程标准,江苏省普通高中课程设置
  10. 多项式事件模型(multinomial event model)