Python图像处理【22】基于卷积神经网络的图像去雾

news/2024/5/25 11:01:50/文章来源:https://blog.csdn.net/qq_30167691/article/details/136613668

基于卷积神经网络的图像去雾

    • 0. 前言
    • 1. 渐进特征融合网络
    • 2. 图像去雾
      • 2.1 网络构建
      • 2.2 模型测试
    • 小结
    • 系列链接

0. 前言

单图像去雾 (dehazing) 是一个具有挑战性的图像恢复问题。为了解决这个问题,大多数算法都采用经典的大气散射模型,该模型是一种基于单一散射和均匀大气介质假设的简化物理模型,但现实环境中的雾霾表述更加复杂。

1. 渐进特征融合网络

在本节中,我们将学习如何使用输入自适应端到端深度学习预训练去雾模型,即渐进特征融合网络 (Progressive Feature Fusion Network, PFFNet),并通过使用 Pytorch 来执行模糊图像的去雾操作。渐进特征融合所采用的 U-Net 架构编码器 - 解码器网络,可直接学习从模糊图像到清晰图像的高度非线性转换函数。深度神经网架构如下图所示:

PFFNet
从以上体系结构图可以看出:

  • 编码器由五个卷积层组成,每个卷积层之后都有非线性 ReLU 激活函数;第一层用于从原始模糊图像中相对较大的局部感受野上的提取特征,然后,依次执行四次下采样卷积操作,以获取图像金字塔
  • 特征转换模块由基于残差的模块组成,深层网络可以表示非常复杂的特征,也可以学习到许多不同尺度的特征,但同时,在使用反向传播进行训练时,经常会遇到消失的梯度问题,而残差网络就是为了解决这一问题而被提出的,可以用于训练更深的网络
  • 解码器由四个反卷积层和一个卷积层组成,与编码器相反,解码器的反卷积层顺序堆叠以恢复图像结构细节

2. 图像去雾

2.1 网络构建

(1) 首先下载预训练网络模型,并导入所需的库,模块和函数:

import torch
import torch.nn as nn
import torch.nn.functional as F
from PIL import Image
from torch.autograd import Variable
from torchvision.transforms import ToTensor, ToPILImage, Normalize, Resize
#from torchviz import make_dot
import matplotlib.pylab as plt 

(2) 定义与深神经网络中不同层相对应的 ConvLayerUpsampleConvLayer 类,所有网络层都继承自 Pytorchnn.module 类;每个层都需要实现自己的 init() (用于初始化参数/成员变量/层)和 forward() 方法(定义前向传播过程中的计算):

class ConvLayer(nn.Module):def __init__(self, in_channels, out_channels, kernel_size, stride):super(ConvLayer, self).__init__()reflection_padding = kernel_size // 2self.reflection_pad = nn.ReflectionPad2d(reflection_padding)self.conv2d = nn.Conv2d(in_channels, out_channels, kernel_size, stride)def forward(self, x):out = self.reflection_pad(x)out = self.conv2d(out)return outclass UpsampleConvLayer(torch.nn.Module):def __init__(self, in_channels, out_channels, kernel_size, stride):super(UpsampleConvLayer, self).__init__()reflection_padding = kernel_size // 2self.reflection_pad = torch.nn.ReflectionPad2d(reflection_padding)self.conv2d = nn.ConvTranspose2d(in_channels, out_channels, kernel_size, stride=stride)def forward(self, x):out = self.reflection_pad(x)out = self.conv2d(out)return out

(3) 接下来,我们用两个 ConvLayer 类实例定义类 ResidualBlock,在 ConvLayer 类实例之间使用 PReLU 激活函数,该类同样继承自 nn.module,并定义 forward() 方法用于前向传播:

class ResidualBlock(nn.Module):def __init__(self, channels):super(ResidualBlock, self).__init__()self.conv1 = ConvLayer(channels, channels, kernel_size=3, stride=1)self.conv2 = ConvLayer(channels, channels, kernel_size=3, stride=1)self.relu = nn.PReLU()def forward(self, x):residual = xout = self.relu(self.conv1(x))out = self.conv2(out) * 0.1out = torch.add(out, residual)return out 

(4) 定义继承自 nn.conv2d 类的 MeanShift 类,通过将 requires_grad 的参数设置为 False,冻结 MeanShift 层:

class MeanShift(nn.Conv2d):def __init__(self, rgb_range, rgb_mean, sign):super(MeanShift, self).__init__(3, 3, kernel_size=1)self.weight.data = torch.eye(3).view(3, 3, 1, 1)self.bias.data = float(sign) * torch.Tensor(rgb_mean) * rgb_range# Freeze the MeanShift layerfor params in self.parameters():params.requires_grad = False

(5) 最后,根据所定义的神经网络层定义深度神经网络类 Net,该类同样需要定义 init() 方法。网络使用了五个 ConvLayer,然后使用四个 UPSampleconvLayer,最后通过 ConvLayer 层后输出,网络使用 LeakyReLU 作为激活函数。
同样,需要定义向前传播方法 forward(),并在每个激活函数后使用双线性上采样:

class Net(nn.Module):def __init__(self, res_blocks=18):super(Net, self).__init__()rgb_mean = (0.5204, 0.5167, 0.5129)self.sub_mean = MeanShift(1., rgb_mean, -1)self.add_mean = MeanShift(1., rgb_mean, 1)self.conv_input = ConvLayer(3, 16, kernel_size=11, stride=1)self.conv2x = ConvLayer(16, 32, kernel_size=3, stride=2)self.conv4x = ConvLayer(32, 64, kernel_size=3, stride=2)self.conv8x = ConvLayer(64, 128, kernel_size=3, stride=2)self.conv16x = ConvLayer(128, 256, kernel_size=3, stride=2)self.dehaze = nn.Sequential()for i in range(1, res_blocks):self.dehaze.add_module('res%d' % i, ResidualBlock(256))self.convd16x = UpsampleConvLayer(256, 128, kernel_size=3, stride=2)self.convd8x = UpsampleConvLayer(128, 64, kernel_size=3, stride=2)self.convd4x = UpsampleConvLayer(64, 32, kernel_size=3, stride=2)self.convd2x = UpsampleConvLayer(32, 16, kernel_size=3, stride=2)self.conv_output = ConvLayer(16, 3, kernel_size=3, stride=1)
()self.relu = nn.LeakyReLU(0.2)def forward(self, x):x = self.relu(self.conv_input(x))res2x = self.relu(self.conv2x(x))res4x = self.relu(self.conv4x(res2x))res8x = self.relu(self.conv8x(res4x))res16x = self.relu(self.conv16x(res8x))res_dehaze = res16xres16x = self.dehaze(res16x)res16x = torch.add(res_dehaze, res16x)res16x = self.relu(self.convd16x(res16x))res16x = F.upsample(res16x, res8x.size()[2:], mode='bilinear')res8x = torch.add(res16x, res8x)res8x = self.relu(self.convd8x(res8x))res8x = F.upsample(res8x, res4x.size()[2:], mode='bilinear')res4x = torch.add(res8x, res4x)res4x = self.relu(self.convd4x(res4x))res4x = F.upsample(res4x, res2x.size()[2:], mode='bilinear')res2x = torch.add(res4x, res2x)res2x = self.relu(self.convd2x(res2x))res2x = F.upsample(res2x, x.size()[2:], mode='bilinear')x = torch.add(res2x, x)x = self.conv_output(x)return x

(6) 定义预训练模型参数位置以及模型使用的残差块数量:

rb = 13
checkpoint = "I-HAZE_O-HAZE.pth"

(7) 实例化 Net() 类并使用 load_state_dict() 方法从检查点加载预训练权重。由于我们不需要训练模型,因此使用测试模式:

net = Net(rb)
net.load_state_dict(torch.load(checkpoint)['state_dict'])
net.eval()

2.2 模型测试

(1) 接下来,使用 open() 函数读取输入图像:

im_path = "pic.png"
im = Image.open(im_path)
h, w = im.size
print(h, w)

(2) 使用 torchvision.transforms 模块中的 ToTensor() 将图像转换为张量对象以输入网络,然后使用输入图像在模型上运行正向传递过程计算输出,最后将输出转换为图像:

imt = ToTensor()(im)
imt = Variable(imt).view(1, -1, w, h)
#im = im.cuda()
with torch.no_grad():imt = net(imt)
out = torch.clamp(imt, 0., 1.)
out = out.cpu()
out = out.data[0]
out = ToPILImage()(out)def plot_image(image, title=None, sz=10):plt.imshow(image)plt.title(title, size=sz)plt.axis('off')
plt.figure(figsize=(20,10))
plt.subplot(121), plot_image(im, 'hazed input')
plt.subplot(122), plot_image(out, 'de-hazed output')
plt.tight_layout()
plt.show() 

去雾结果

小结

图像去雾已成为计算机视觉的重要研究方向,在雾、霾等恶劣天气下拍摄的的图像通常由于大气散射的作用,图像质量严重下降使颜色偏灰白色,对比度降低,物体特征难以辨认,还会影响图像的分析与处理。因此,需要使用图像去雾技术来增强或修复图像,以改善视觉效果并便于图像的后续处理。在本节中,我们学习了一种基于卷积神经网络的图像去雾模型,通过使用训练后的模型可以显著改善图像视觉效果。

系列链接

Python图像处理【1】图像与视频处理基础
Python图像处理【2】探索Python图像处理库
Python图像处理【3】Python图像处理库应用
Python图像处理【4】图像线性变换
Python图像处理【5】图像扭曲/逆扭曲
Python图像处理【6】通过哈希查找重复和类似的图像
Python图像处理【7】采样、卷积与离散傅里叶变换
Python图像处理【8】使用低通滤波器模糊图像
Python图像处理【9】使用高通滤波器执行边缘检测
Python图像处理【10】基于离散余弦变换的图像压缩
Python图像处理【11】利用反卷积执行图像去模糊
Python图像处理【12】基于小波变换执行图像去噪
Python图像处理【13】使用PIL执行图像降噪
Python图像处理【14】基于非线性滤波器的图像去噪
Python图像处理【15】基于非锐化掩码锐化图像
Python图像处理【16】OpenCV直方图均衡化
Python图像处理【17】指纹增强和细节提取
Python图像处理【18】边缘检测详解
Python图像处理【19】基于霍夫变换的目标检测
Python图像处理【20】图像金字塔
Python图像处理【21】基于卷积神经网络增强微光图像

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

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

相关文章

实战案例——Kafka集群部署

1. 规划节点 IP主机名节点192.168.100.10zookeeper1集群节点192.168.100.20zookeeper2集群节点192.168.100.30zookeeper集群节点 2. 基础准备 使用ZooKeeper集群搭建的3个节点来构建Kafka集群,因为Kafka服务依赖于ZooKeeper服务, 所以不再多创建云主机…

面试题:分布式锁用了 Redis 的什么数据结构

在使用 Redis 实现分布式锁时,通常使用 Redis 的字符串(String)。Redis 的字符串是最基本的数据类型,一个键对应一个值,它能够存储任何形式的字符串,包括二进制数据。字符串类型的值最多可以是 512MB。 Re…

Croissant:Google新推出的一个为机器学习准备的数据集元数据格式

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗?订阅我们的简报,深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同,从行业内部的深度分析和实用指南中受益。不要错过这个机会,成为AI领…

OSCP靶场--Astronaut

OSCP靶场–Astronaut 考点(1.CVE-2021-21425getshell 2.suid php提权) 1.nmap扫描 ┌──(root㉿kali)-[~/Desktop] └─# nmap -sV -sC -p- 192.168.163.12 --min-rate 2500 Starting Nmap 7.92 ( https://nmap.org ) at 2024-03-14 01:24 EDT Nmap scan report for 192.16…

【AI视野·今日NLP 自然语言处理论文速览 第八十四期】Thu, 7 Mar 2024

AI视野今日CS.NLP 自然语言处理论文速览 Thu, 7 Mar 2024 Totally 52 papers 👉上期速览✈更多精彩请移步主页 Daily Computation and Language Papers The Heuristic Core: Understanding Subnetwork Generalization in Pretrained Language Models Authors Adith…

java中几种对象存储(文件存储)中间件的介绍

一、前言 在博主得到系统中使用的对象存储主要有OSS(阿里云的对象存储) COS(腾讯云的对象存储)OBS(华为云的对象存储)还有就是MinIO 这些玩意。其实这种东西大差不差,几乎实现方式都是一样&…

javaweb数据传参类型(2)

前言 友友们好呀,今天来分享一下对于各种数据类型传参的问题,今天陪伴我们的云海 目录 前言 数组集合传参 补充 日期参数 补充 Json格式数据传参 补充 路径参数 补充 今日分享 ​​​​​​​数组集合传参 类似于我们之前进行的简单的参数传递…

Web Servlet

目录 1 简介2 创建Servlet项目并成功发布运行3 新加Servlet步骤4 Servlet项目练习5 Servlet运行原理6 操作 HTTP Request头的方法(部分方法示例)7 操作 HTTP Response头的方法(部分方法示例)8 两种重定向(页面跳转)方法9 Cookie9.1 Cookie工作原理9.2 cookie构成9.3 Servlet 操…

企业领导者变革八步法:理论框架与案例分析

在当今竞争激烈的市场环境中,企业领导者面临着前所未有的变革挑战。变革不仅是企业生存和发展的关键,更是领导者展现领导才能的舞台。John Kotter提出的面向转型组织的领导变革八步法,为企业领导者提供了一套全面、系统的变革管理框架。本文将…

安卓多个listView拖动数据交换位置和拖动

注意这里只是给出大概思路&#xff0c;具体可以参考修改自己想要的 public class MainActivity extends AppCompatActivity {private ListView listView1;private ListView listView2;private ArrayAdapter<String> adapter1;private ArrayAdapter<String> adapter…

linux系统下,配置开机自启脚本常见的5种方法

✨✨ 欢迎大家来到景天科技苑✨✨ 🎈🎈 养成好习惯,先赞后看哦~🎈🎈 所属的专栏:linux基础与进阶,shell脚本编写实战 景天的主页:景天科技苑 文章目录 linux下设置开机自动运行脚本的5种方法一、编辑/etc/rc.d/rc.local文件1、在自己需要启动的文件目录中编写一个…

代码随想录算法训练营第六天| 242.有效字母的异位词、349.两个数组的交集、202快乐数、1.两数之和

系列文章目录 目录 系列文章目录242.有效的字母异位词349. 两个数组的交集①使用HashSet②使用Hash数组 202. 快乐数1. 两数之和①暴力解法&#xff08;时间复杂度不符合要求&#xff09;②使用HashMap法 242.有效的字母异位词 这道题是数组在哈希表中的典型应用。 因为只有2…

Acer宏碁非凡Swift SFG16-71工厂模式原厂Win11系统,预装OEM系统恢复开箱状态

宏基笔记本电脑SFG16-71原装出厂Windows11系统安装工厂包下载&#xff0c;带恢复重置功能 链接&#xff1a;https://pan.baidu.com/s/1JK02kBbwKG_cIBNlEOzrOw?pwdzdfm 提取码&#xff1a;zdfm 原装工厂包系统自带所有驱动、Office办公软件、出厂时自带主题壁纸图片、系统…

伪分布式Spark集群搭建

一、软件环境 软 件 版 本 安 装 包 VMware虚拟机 16 VMware-workstation-full-16.2.2-19200509.exe SSH连接工具 FinalShell Linux OS CentOS7.5 CentOS-7.5-x86_64-DVD-1804.iso JDK 1.8 jdk-8u161-linux-x64.tar.gz Spark 3.2.1 spark-3.2.1-bin-…

STM32/GD32——I2C通信协议

芯片选型 Ciga Device — GD32F470系列 通讯规则 I2C协议&#xff08;或称IIC&#xff09;是由飞利浦&#xff08;现在的恩智浦半导体&#xff09;公司开发的一种通用的总线协议。它使用两根线&#xff08;时钟线和数据线&#xff09;来传输数据&#xff0c;支持多个设备共享…

如何用postman进行http接口测试?

HTTP的接口测试工具有很多&#xff0c;可以进行http请求的方式也有很多&#xff0c;但是可以直接拿来就用&#xff0c;而且功能还支持的不错的&#xff0c;我使用过的来讲&#xff0c;还是postman比较上手。 优点&#xff1a; 1、支持用例管理 2、支持get、post、文件上传、…

python 实现阿里云OSS文件上传

因为我们出口的带宽限制&#xff0c;测试经常找我给他上传个包到阿里云的对象存储&#xff0c;虽然传起来也不是很费事&#xff0c;但是出于运维的职业素养&#xff0c;特意写了一个自动上传的接口&#xff0c;代码如下&#xff1a; # -*- coding: UTF-8 -*- from flask imp…

docker-swarm集群管理命令

为什么选择swarm集群&#xff1f; 灵魂疑问&#xff1a;同样是集群&#xff0c;为什么选择docker swarm&#xff0c;而不不选择k8s或者k3s&#xff1f; 我的需求场景&#xff1a;不想直接用docker或者java -jar直接跑&#xff0c;修改前是使用java -jar方式&#xff0c;这两种…

java019 - Java内部类

1、内部类概述 1.1 内部类访问特点 内部类可以访问外部类的成员&#xff0c;包括私有外部类要访问内部类的成员&#xff0c;必须创建对象 代码&#xff1a; outer类&#xff1a;inner为内部类 2、成员内部类 2.1 成员内部类 代码&#xff1a; 外部类&#xff1a; 测试类中…

Linux系统安装APITable智能表格并结合内网穿透实现公网访问本地服务

文章目录 前言1. 部署APITable2. cpolar的安装和注册3. 配置APITable公网访问地址4. 固定APITable公网地址 前言 vika维格表作为新一代数据生产力平台&#xff0c;是一款面向 API 的智能多维表格。它将复杂的可视化数据库、电子表格、实时在线协同、低代码开发技术四合为一&am…