目录
前言
一、图像加雾
1、基于传统方法的雾图合成
2、基于深度学习的雾图合成
3、基于Lightroom Classic实现软件加雾
4、基于深度图的方法实现加雾
二、开源的数据集
三、参考文章
前言
在去雾任务当中,训练和评估去雾算法需要大量的带有雾霾和无雾霾的图像对。由于实际拍摄的带雾霾的图像不易获得并且不可控,因此研究者常常通过加雾(Image Fogging)技术来人工生成含雾图像,以丰富数据集。这不仅有助于生成多样化的训练数据,还能在控制实验中评估去雾算法的性能。本文将探讨图像加雾的基本原理和常用方法,并介绍一些用于图像加雾的具体技术。
一、图像加雾
1、基于传统方法的雾图合成
大气散射模型: 大气散射是指光线在大气中传播时,由于空气中的微小颗粒和气体分子的散射,使得光线强度随着传播距离的增加而衰减。根据贝尔-朗伯定律(Beer-Lambert Law),光强度 可以表示为:
其中:
- 是初始光强度。
- 是衰减系数,控制雾霾的浓度。
- d 是光线传播的距离。
雾霾效果模拟:对于图像中的每一个像素,计算其到中心点的距离 d。使用指数衰减函数
计算雾霾的强度。调整每个像素的亮度,使其受到雾霾的影响。具体公式为:
new_pixel=original_pixel×td+brightness×(1−td)
其中 brightness 参数控制了雾霾的亮度。
下面让我们实现这个算法:
import numpy as np
def 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.0
row, col, chs = image.shape
size = np.sqrt(max(row, col)) # Atomization size
center = (row // 2, col // 2) # Atomization center
for j in range(row):
for l in range(col):
d = -0.04 * np.sqrt((j - center[0]) ** 2 + (l - center[1]) ** 2) + size
td = 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_f
if __name__ == '__main__':
import pyzjr
path = 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 np
def 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.0
row, col, chs = image.shape
size = np.sqrt(max(row, col)) # Atomization size
center = (row // 2, col // 2) # Atomization center
for j in range(row):
for l in range(col):
d = -0.04 * np.sqrt((j - center[0]) ** 2 + (l - center[1]) ** 2) + size
td = 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_f
def 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.0
row, col, chs = image.shape
size = np.sqrt(max(row, col)) # Atomization size
center = (row // 2, col // 2) # Atomization center
y, x = np.ogrid[:row, :col]
dist = np.sqrt((x - center[1])**2 + (y - center[0])**2)
d = -0.04 * dist + size
td = 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_f
if __name__ == '__main__':
import pyzjr
from pyzjr.dlearn.tools import Runcodes
path = 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 cv2
def 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)) * 255
normalized_disparity_image = normalized_disparity_image.astype(np.uint8)
return normalized_disparity_image
def 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 + 1
height = header['dataWindow'].max.y + 1
pixel_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_buffer
if __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 Drivehttps://drive.google.com/drive/folders/1mHr9p-c895tFtyRLz1JEeEGAurTmj_v-RSHaze、RESIDE-OUT、RESIDE-IN、RESIDE-6K
data - Google Drivehttps://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博客