图像加雾算法的研究与应用

目录

前言

一、图像加雾

1、基于传统方法的雾图合成

2、基于深度学习的雾图合成

3、基于Lightroom Classic实现软件加雾

4、基于深度图的方法实现加雾

二、开源的数据集

三、参考文章


前言

在去雾任务当中,训练和评估去雾算法需要大量的带有雾霾和无雾霾的图像对。由于实际拍摄的带雾霾的图像不易获得并且不可控,因此研究者常常通过加雾(Image Fogging)技术来人工生成含雾图像,以丰富数据集。这不仅有助于生成多样化的训练数据,还能在控制实验中评估去雾算法的性能。本文将探讨图像加雾的基本原理和常用方法,并介绍一些用于图像加雾的具体技术。

一、图像加雾

1、基于传统方法的雾图合成

大气散射模型: 大气散射是指光线在大气中传播时,由于空气中的微小颗粒和气体分子的散射,使得光线强度随着传播距离的增加而衰减。根据贝尔-朗伯定律(Beer-Lambert Law),光强度 I 可以表示为:

I(d)=I_{0}\cdot e^{-\beta d}

其中:

  • I_{0} 是初始光强度。
  • \beta  是衰减系数,控制雾霾的浓度。
  • d   是光线传播的距离。

雾霾效果模拟:对于图像中的每一个像素,计算其到中心点的距离 d。使用指数衰减函数

td = e^{-\beta d}计算雾霾的强度。调整每个像素的亮度,使其受到雾霾的影响。具体公式为:

new_pixel=original_pixel×td+brightness×(1−td)

其中 brightness 参数控制了雾霾的亮度。

下面让我们实现这个算法:

import numpy as npdef addfog(image, beta=0.05, brightness=0.5):"""对输入的图像添加雾霾效果。Args:image (numpy.ndarray): 输入的图像,范围在0-255.beta (float, optional): 控制雾霾效果的参数.beta值越大,雾霾效果越明显.默认为0.05.brightness (float, optional): 雾霾的亮度值.该值越大,图像整体亮度越高.默认为0.5.Returns:numpy.ndarray: 添加雾霾效果后的图像,数据类型为uint8,范围在0-255。"""img_f = np.array(image, dtype=np.float32) / 255.0row, col, chs = image.shapesize = np.sqrt(max(row, col))  # Atomization sizecenter = (row // 2, col // 2)  # Atomization centerfor j in range(row):for l in range(col):d = -0.04 * np.sqrt((j - center[0]) ** 2 + (l - center[1]) ** 2) + sizetd = np.exp(-beta * d)img_f[j][l][:] = img_f[j][l][:] * td + brightness * (1 - td)img_f = np.clip(img_f * 255, 0, 255).astype(np.uint8)return img_fif __name__ == '__main__':import pyzjrpath = r'test1.png'image = pyzjr.imreader(path)print(image.shape)image_fog = addfog(image)print(image_fog.shape)pyzjr.display("Comparison between original image and fogged image",[[image, image_fog]], 0.4)

关于光线传播的距离d,它的系数-0.04应该是一个经验值,主要是用于调整距离对雾霾强度的影响。 可以根据实际效果进行调整,较小的系数会使距离对雾霾效果的影响减小,反之则增大。添加 size 是用来调节雾霾的范围大小的。通常情况下,雾化效果在中心点附近比较强烈,随着距离中心点的增加,雾化效果逐渐减弱。

加雾效果如下所示: 

在运行期间,时间明显比较长,现在我们来写一个优化的版本吧

这个时间长主要是因为这个嵌套循环,所以我们可以利用NumPy的矢量化操作来提高计算效率,可以使用 np.ogrid 生成行和列的索引,并计算每个像素点到中心点的距离。计算 td 采用矢量化方式,避免使用双重循环,提高效率。用 [..., np.newaxis] 进行广播,使得每个通道都应用相同的雾霾效果。这样就能显著提升大图像的处理速度,特别是在高分辨率图像上效果明显。

import numpy as npdef addfogv1(image, beta=0.05, brightness=0.5):"""对输入的图像添加雾霾效果。Args:image (numpy.ndarray): 输入的图像,范围在0-255.beta (float, optional): 控制雾霾效果的参数.beta值越大,雾霾效果越明显.默认为0.05.brightness (float, optional): 雾霾的亮度值.该值越大,图像整体亮度越高.默认为0.5.Returns:numpy.ndarray: 添加雾霾效果后的图像,数据类型为uint8,范围在0-255。"""img_f = np.array(image, dtype=np.float32) / 255.0row, col, chs = image.shapesize = np.sqrt(max(row, col))  # Atomization sizecenter = (row // 2, col // 2)  # Atomization centerfor j in range(row):for l in range(col):d = -0.04 * np.sqrt((j - center[0]) ** 2 + (l - center[1]) ** 2) + sizetd = np.exp(-beta * d)img_f[j][l][:] = img_f[j][l][:] * td + brightness * (1 - td)img_f = np.clip(img_f * 255, 0, 255).astype(np.uint8)return img_fdef addfogv2(image, beta=0.05, brightness=0.5):"""对输入的图像添加雾霾效果的高效实现。Args:image (numpy.ndarray): 输入的图像,范围在0-255.beta (float, optional): 控制雾霾效果的参数. beta值越大, 雾霾效果越明显. 默认为0.05.brightness (float, optional): 雾霾的亮度值. 该值越大, 图像整体亮度越高. 默认为0.5.Returns:numpy.ndarray: 添加雾霾效果后的图像,数据类型为uint8,范围在0-255。"""img_f = image.astype(np.float32) / 255.0row, col, chs = image.shapesize = np.sqrt(max(row, col))  # Atomization sizecenter = (row // 2, col // 2)  # Atomization centery, x = np.ogrid[:row, :col]dist = np.sqrt((x - center[1])**2 + (y - center[0])**2)d = -0.04 * dist + sizetd = np.exp(-beta * d)img_f = img_f * td[..., np.newaxis] + brightness * (1 - td[..., np.newaxis])img_f = np.clip(img_f * 255, 0, 255).astype(np.uint8)return img_fif __name__ == '__main__':import pyzjrfrom pyzjr.dlearn.tools import Runcodespath = r'test1.png'image = pyzjr.imreader(path)with Runcodes("加雾算法v1版本"):image_fogv1 = addfogv1(image)with Runcodes("加雾算法v2版本"):image_fogv2 = addfogv2(image)pyzjr.display("Comparison between original image and fogged image",[[image_fogv1, image_fogv2]], 0.4)

加雾v1与v2版本的效果: 

在时间对比上有很大提升

加雾算法v1版本: 10.10729 sec,加雾算法v2版本: 0.14432 sec

2、基于深度学习的雾图合成

利用成对数据训练模型,基于生成对抗网络(GAN)或者自编码器(Autoencoder)实现的深度学习方法可以实现端到端的合成雾图。然而,由于这些方法同样需要训练数据,合成的雾图和真实雾图之间可能存在一定的差异。

除此之外,我一直在思考一般我们做的去雾任务,能不能反过来做,把去雾的输入输出反过来训练,即将清晰图像作为输入,雾图像作为输出来训练模型,一般的模型都可以做到加雾任务。这种反向的方法,可能存在诸多的问题,但用深度学习的方法应该能够更好的控制雾的浓度和分布。

3、基于Lightroom Classic实现软件加雾

打开Lrc软件,左上角点击文件,导入照片和视频

点击图库,选择图片,修改图片,点击基本,调整去朦胧的值,往小的调整。 

这是拉到了-100的效果图 

如果想要恢复原来的照片,点击右下角「复位」按钮,就可以使照片恢复到最初的样子。也可以使用快捷键ctrl+z。

这是拉到了+100的效果图 

比起原图也更加清晰,我觉得可以采用这样的方式去丰富我们的数据集。

4、基于深度图的方法实现加雾

Synscapes这个数据集很大,有180多个G,你可以从这里进行下载,全部下载完之后才能解压。

Synscapes data set (liu.se)

从exr文件读取深度信息并进行可视化

import OpenEXR
import numpy as np
import Imath
import cv2def synscapes_depth_as_disparity(depth_image):"""将Synscapes深度图像转换为视差图像。"""# 将深度图归一化到0-1范围,并将深度值转换为视差值normalized_depth_image = depth_image / np.max(depth_image)disparity_image = 1.0 / (normalized_depth_image + 1e-5)# 将视差图归一化到0-255范围normalized_disparity_image = (disparity_image - np.min(disparity_image)) / (np.max(disparity_image) - np.min(disparity_image)) * 255normalized_disparity_image = normalized_disparity_image.astype(np.uint8)return normalized_disparity_imagedef read_depth_from_exr(exr_file_path):"""使用OpenEXR库打开指定的EXR文件 """exr_file = OpenEXR.InputFile(exr_file_path)header = exr_file.header()width = header['dataWindow'].max.x + 1height = header['dataWindow'].max.y + 1pixel_type = Imath.PixelType(Imath.PixelType.FLOAT)z_channel = exr_file.channel('Z', pixel_type=pixel_type)z_buffer = np.frombuffer(z_channel, dtype=np.float32)z_buffer = z_buffer.reshape((height, width))return z_bufferif __name__=="__main__":exr_file_path = r"F:\dataset\Dehazy\synscapes\Synscapes\img\depth\3.exr"depth_image = read_depth_from_exr(exr_file_path)normalized_disparity_image = synscapes_depth_as_disparity(depth_image)cv2.imshow("Disparity Image", normalized_disparity_image)cv2.waitKey(0)cv2.destroyAllWindows()

加雾效果对比图

因为这部分工作不是我做的,所以代码不能开源,只能给大家看看效果。

二、开源的数据集

ITS, SOTS, OHAZE, Dense-haze下载路径

dataset - Google Driveicon-default.png?t=N7T8https://drive.google.com/drive/folders/1mHr9p-c895tFtyRLz1JEeEGAurTmj_v-RSHaze、RESIDE-OUT、RESIDE-IN、RESIDE-6K

data - Google Driveicon-default.png?t=N7T8https://drive.google.com/drive/folders/1oaQSpdYHxEv-nMOB7yCLKfw2NDCJVtrx大家找开源数据集可以从近两年的去雾的论文的开源仓库里面找到。

三、参考文章

数据增强:图片加雾效果实现Python_图像加雾算法-CSDN博客

https://www.scirp.org/pdf/jcc_2021110215052004.pdf

域适应加雾代码:通过《bringing old photos back to life 》_生成雾图-CSDN博客

如何在 Lightroom 中使用去朦胧功能?_lightroom去朦胧-CSDN博客

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

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

相关文章

聊聊几种常见的分布式Session解决方案

highlight: xcode theme: vuepress 问题引入:什么是分布式Session? 分布式 Session 是指在多台服务器之间共享和管理用户的会话数据,使得用户的会话状态能够在不同的服务器上保持一致。这样,无论用户的请求被路由到哪台服务器&…

常见的几种编码方式

常见的编码方式及其特点: 编码方式的设计是为了适应不同的字符集和应用需求,因此它们在表示字符时使用的位数和字节数各不相同 常见编码方式及其位数和字节数 ASCII(American Standard Code for Information Interchange)&#x…

C#语言进阶(二)—事件 第三篇(事件访问器)

总目录 C# 语法总目录 系列链接 C#语言进阶(二) 事件 第一篇(发布订阅模式) C#语言进阶(二) 事件 第二篇(.net标准事件模型) C#语言进阶(二) 事件 第二篇(事件访问器) 事件 第三篇目录 事件 第三篇3. 事件访问器 事件 第三篇 3. 事件访问器 默认情况下,编…

【Go语言精进之路】构建高效Go程序:掌握变量、常量声明法则与iota在枚举中的奥秘

🔥 个人主页:空白诗 文章目录 引言一、变量1.1 基础知识1.2 包级变量的声明形式深入解析📌 声明并同时显式初始化📌 声明但延迟初始化📌 声明聚类与就近原则 1.3 局部变量的声明形式深入探讨📌 延迟初始化的…

你认识nginx吗,nginx是做什么的,nginx可以做什么 --1)nginx介绍

一.Nginx 介绍 Nginx(发音同engine x)是一个异步框架的 Web 服务器,也可以用作反向代理,负载平衡器 和 HTTP 缓存。该软件由 Igor Sysoev 创建,并于2004年首次公开发布。同名公司成立于2011年,以提供支持。…

PHP:集成Xunsearch生成前端搜索骨架

如果是安装宝塔,我们在集成xunsearch的时候就会比较简单,后面我们在介绍其他的接入方式; 首先我们进入到宝塔管理后台:【软件商店】-【输入xun】-【点击xunsearch】直接安装即可 安装成功之后,会自动在www/server中创…

spdlog日志库源码:全局管理类registry

概述 已经有了用于接收前端用户log消息的类logger,代表log消息的类是log_msg,后端写log消息到目标文件的类sink,格式化log消息为最终字符串的类formatter,解析pattern flag的类pattern_formatter等等。 每次使用时,可…

Forth Python语言:深度解析其四维、五维、六维与七维之奥秘

Forth Python语言:深度解析其四维、五维、六维与七维之奥秘 在编程语言的浩瀚星空中,Forth Python以其独特的魅力与深邃的内涵,吸引着众多探索者的目光。然而,这门语言究竟有何独到之处?本文将从四维、五维、六维和七…

大模型高级 RAG 检索策略:自动合并检索

节前,我们星球组织了一场算法岗技术&面试讨论会,邀请了一些互联网大厂朋友、参加社招和校招面试的同学. 针对算法岗技术趋势、大模型落地项目经验分享、新手如何入门算法岗、该如何准备、面试常考点分享等热门话题进行了深入的讨论。 汇总合集&…

Flutter 中的 CupertinoSliverNavigationBar 小部件:全面指南

Flutter 中的 CupertinoSliverNavigationBar 小部件:全面指南 Flutter 是一个由 Google 开发的跨平台 UI 框架,它允许开发者使用 Dart 语言来构建高性能、美观的移动、Web 和桌面应用。在 Flutter 的丰富组件库中,CupertinoSliverNavigation…

比较3维空间中4个点的不同结构

在4*4*4的3维空间中,取4个点共有635376种可能,有209个结构,继续按旋转对称分类则只有55个不同的结构。如其中的4t12 4个点在同一个平面,有1个点与其中的3个点不在同一行也不在同一列,这样的位置不止一个 这两个结构都是…

Apache Calcite - 自定义数据源适配之访问内存列表

前言 上一篇文章中学习了Calcite基本概念&#xff0c;其中框架的核心能力是通过统一的Sql访问不同来源的数据。这篇文章中将通过一个简单的例子学习如何实现改功能。 最终通过sql来访问Java List中的数据。 准备工作 maven依赖 <dependency><groupId>org.apache…

ubuntu系统下安装mysql的步骤详解

一、下载安装包 下载地址&#xff1a; https://dev.mysql.com/downloads/repo/apt 跳转到这个页面&#xff1a; 直接点击Download。 直接点击最下面的开始下载安装包即可。 二、将安装包下载到ubuntu系统中 先将用户切换成root用户&#xff0c;把下载好的安装包复制到桌面上&…

域名更换服务器的原因

在互联网的运营过程中&#xff0c;域名更换服务器是一个常见的操作&#xff0c;可能是由于业务扩展、性能需求、成本考虑或服务质量等多种因素。然而&#xff0c;这个过程如果处理不当&#xff0c;可能会导致网站访问中断、搜索引擎排名下降或用户体验受损。本文将探讨在域名更…

系统架构设计师【第11章】: 未来信息综合技术 (核心总结)

文章目录 11.1 信息物理系统技术概述11.1.1 信息物理系统的概念11.1.2 CPS的实现11.1.3 信息物理系统的建设和应用 11.2 人工智能技术概述11.2.1 人工智能的概念11.2.2 人工智能的发展历程11.2.3 人工智能关键技术 11.3 机器人技术概述11.3.1 机器人的概念11.3.2 机…

丛林生存法则其实就两个字:输出

不管你是在上班&#xff0c;还是在灵活就业&#xff0c;现在的大环境下&#xff0c;你要想活下来&#xff0c;生存下去&#xff0c;一定要记住这两个字&#xff1a;输出。如果你能记住更多的字&#xff0c;那便是持续高水平的输出。 你如果是大厂程序员&#xff0c;你肯定发现…

Linux DHCP server 配置

参考&#xff1a;linux dhcp配置多vlan ip_linux 接口vlan-CSDN博客 配置静态IP地址&#xff1a; 给固定的MAC地址分配指定的IP地址&#xff0c;固定的IP地址不必包含在指定的IP池中&#xff0c;如果包含在IP地址池中&#xff0c;固定的IP地址会从IP地址池中移除 配置方法&…

清洁力强的洗地机前十名排行榜:2024十大洗地机热销款式好用不踩雷

如今&#xff0c;洗地机行业竞争激烈&#xff0c;各品牌紧紧抓住用户对智能化和深度清洁的需求&#xff0c;深入研究创新。经过几轮行业内部的激烈竞争后&#xff0c;许多厂商在宣传中各说各的&#xff0c;对洗地机的重要参数描述不一&#xff0c;给消费者的选择带来了不少困惑…

【CVPR_2024】:逐元素乘积为什么会产生如此令人满意的结果?

写在前面&#xff1a;本博客仅作记录学习之用&#xff0c;部分图片来自网络&#xff0c;如需引用请注明出处&#xff0c;同时如有侵犯您的权益&#xff0c;请联系删除&#xff01; 文章目录 前言论文重写星形运算一层网络推广多层网络特殊情况 W 1 W_1 W1​和/或 W 2 W_2 W2​…

JDK版本特性(JDK8\11\17\21版本)

JDK版本特性 Oracle官网https://www.oracle.com/java/technologies/java-se-support-roadmap.html Oracle官网中JDK版本的说明&#xff0c;Java SE 8、11、17和21是LTS版本。也就是长期支持版本。 我们针对这几个版本了解学习下对应版本的新特性。 JDK8版本 正式发布于2014…