
雾霾是一种常见的大气现象,会损害日常生活和机器视觉系统。雾霾的存在降低了场景的能见度,影响了人们对物体的判断,厚重的雾霾甚至会影响日常活动,比如与交通安全。对于计算机视觉来说,雾霾在大多数情况下会通过部分或完全遮挡物体而降低捕获图像的质量。它可以影响模型在高级视觉任务中的可靠性,进一步误导机器系统,如自动驾驶。所有这些都使图像去朦胧化成为一项有意义的低层次视觉任务。
因此,许多研究人员试图从朦胧的图像中恢复高质量的清晰场景。在深度学习被广泛用于计算机视觉任务之前,图像脱灰算法主要依赖于各种先验假设和大气散射模型。这些基于统计规则的方法的处理流程具有良好的可解释性,但在面对复杂的现实世界场景时,它们可能会表现出缺点。因此,最近在图像减淡方面的大多数努力都采用了深度学习模型。
在这篇文章中,我们将介绍图像消隐的数学基础,并讨论消隐的不同类别。我们将审视深度学习文献中提出的最流行的图像去hazing架构,并详细讨论图像去hazing的应用。
图像消隐的数学模型
大气散射模型一直是朦胧图像生成过程的经典描述。
这个数学模型背后的想法是,光线在到达相机镜头之前会被空气中的悬浮颗粒(雾霾)散射掉。实际捕获的光量既取决于有多少雾霾,反映在β中 , 也取决于物体离相机有多远,反映在 d(x) 中。
深度学习模型试图学习传输矩阵。大气中的光线被单独计算,并根据大气散射模型恢复干净的图像。
图像脱毛的评价指标
视觉线索不足以评估和比较不同的脱毛方法的性能,因为它们在本质上是非常主观的。为了公平地比较各种模型,需要有一个通用的量化指标来衡量脱hazing的性能。
峰值信噪比(PSNR)和结构相似度(SSIM)指数是两个最常用的评价指标,用于评价去噪性能。一般来说,PSNR和SSIM指标都是用来对去噪方法进行公平评估的,与最先进的方法相比。
让我们接下来讨论这些指标。
PSNR
峰值信噪比(PSNR)是一个客观指标,用于衡量由去雾化算法获得的无雾化图像与地面真实图像之间的信号失真程度。"MSE "代表图像之间的像素平均平方误差,"M "是图像中一个像素的最大可能值(对于8位RGB图像,我们习惯用M=255)。PSNR的值越高(以分贝/分贝为单位),重建质量就越好。在Python3 ,PSNR可以像下面这样进行编码。
import numpy as np
from math import log10
def PSNR(img1, img2):
mse = np.mean((img1 - img2) ** 2)
if(mse == 0): # MSE is zero means no noise is present in the signal .
# Therefore PSNR have no importance.
return 100
max_pixel = 255.0
psnr = 10 * log10(max_pixel**2 / mse)
return psnr
SSIM
由于PSNR在人的视觉判断方面是无效的,因此,许多研究人员利用结构相似性指数指标(SSIM),这是一个主观的衡量标准,从对比度、亮度和地面真实图像与脱敏图像之间的结构一致性方面来评估脱敏性能。
SSIM的范围在0到1之间,数值越高表示结构一致性越强,因此脱hazing效果越好。在Python3 ,skimage 包中包含SSIM函数,可以很容易地使用。
from skimage.metrics import structural_similarity as ssim
similarity = ssim(img1, img2)
单一图像与多重图像的脱hazing
根据可用的输入信息量的不同,存在两种类型的图像脱hazing方法。在单图像去朦胧中,只有一个朦胧的图像是可用的,它需要被映射到其去朦胧的对应物。然而,在多图像去朦胧中,同一场景或物体的多张朦胧图像是可用的,它们都被用来映射到单一的去朦胧图像。
在单图像去雾方法中,由于可用的输入信息量较少,在重建的去雾图像中可能会出现虚假的模式,这与原始图像的背景没有明显的联系。这可能会产生模糊性,进而导致最终(人类)决策者的误导。
在完全监督的多图像去雾方法中,通常在干净的图像上使用不同的退化函数(地面真相),以获得同一场景中略有不同类型的雾化图像。由于可用信息的多样性,这有助于模型做出更好的概括。
直观地讲,我们可以理解,多图像去朦胧表现得更好,因为它有更多的输入信息可以使用。然而,在这种情况下,计算成本也会增加数倍,这使得它在许多有大量资源限制的应用场景中不可行。另外,获得同一物体的多张朦胧图像往往很繁琐,也不实用。因此,在监控、水下探测等应用中,单幅图像去朦胧与现实世界的关系更为密切,尽管它是一个更具挑战性的问题陈述。
然而,在某些应用领域,如遥感领域,同一场景的几张朦胧图像往往是现成的,因为多颗卫星用多部相机(往往是不同的曝光设置)同时捕捉同一地点的图像。
一种使用多图像去雾的方法是基于CNN的RSDehazeNet模型,用于去除多光谱遥感数据中的雾霾。RSDehazeNet由三种类型的模块组成:
- 通道细化模块或CRB,用于模拟通道特征之间的相互依赖关系,因为多光谱图像的通道是高度相关的。
- 残余通道细化块(RCRB),因为带有残余块的CNN模型能够捕捉到弱信息,推动网络以更快的速度收敛,性能更优越。
- 特征融合块(FFB)用于特征图的全局融合和多光谱RS图像的去模糊化。
脱灰方法的分类
根据朦胧输入图像的地面真实图像的可用性,图像去模糊方法可以分为以下几类:
- 有监督的方法
- 半监督的方法
- 无监督的方法
让我们接下来讨论这些方法。
有监督的方法
在完全监督的方法中,对应于朦胧图像的脱灰图像都可以用来训练网络。监督脱灰模型通常需要不同类型的监督信息来指导训练过程,如透射图、大气光、无霾图像标签等。
FAMED-Net或快速准确的多尺度消隐网络就是这样一种有监督的方法,它解决了单幅图像的消隐问题,其目的是推断网络的速度。FAMED-Net由一个完全卷积的端到端多尺度网络(有三个不同尺度的编码器)组成,可以有效地处理任意大小的模糊图像。
半监督方法
半监督学习是一种机器学习范式,在这个范式中,大数据集的一个小子集(比如5-10%的数据)包含了地面真实标签。因此,在网络训练中,一个模型要承受大量的无标签数据和少数有标签的样本。与完全监督的方法相比,半监督的方法在图像去模糊化方面受到的关注较少。
PSD或有原则的合成-真实脱毛是一个半监督的脱毛模型,包括两个阶段:监督的预训练和无监督的微调。在预训练中,作者使用了合成数据,在无监督的微调中使用了真实的朦胧的无标签数据,在合成到真实的图像转换中采用了无监督的域适应。
有监督的方法
在无监督学习中,数据标签是完全缺失的。一个深度网络需要完全使用非结构化的数据进行训练。这使得图像脱毛问题更具挑战性。
例如,SkyGAN是一个无监督的去模糊模型,它利用生成对抗网络(GAN)架构对高光谱图像进行去模糊处理。SkyGAN使用具有循环一致性的条件GAN(cGAN)框架,也就是说,添加了一个正则化参数,其假设是:当退化时,脱灰的图像应该再次返回模糊的输入图像。
SkyGAN模型获得的结果令人印象深刻,因为它们甚至超过了完全监督的方法。
监督下的单次消隐问题的代码中最重要的部分是策划自定义数据集,以获得朦胧和干净的图像。下面是一个PyTorch的代码。
import torch
import torch.utils.data as data
import torchvision.transforms as transforms
import numpy as np
from PIL import Image
import os
class DehazingDataset(data.Dataset):
def __init__(self, hazy_images_path, clean_images_path, transform=None):
#Get the images
self.hazy_images = [hazy_images_path + f for f in os.listdir(hazy_images_path) if f.endswith('.jpg') or f.endswith('.png') or f.endswith('.jpeg')]
self.clean_images = [clean_images_path + f for f in os.listdir(clean_images_path) if f.endswith('.jpg') or f.endswith('.png') or f.endswith('.jpeg')]
#Filter the images to ensure they are counterparts of the same scene
self.filter_files()
self.size = len(self.hazy_images)
self.transform=transform
def filter_files(self):
assert len(self.hazy_images) == len(self.clean_images)
hazy_ims = []
clean_ims = []
for hazy_img_path, clean_img_path in zip(self.hazy_images, self.clean_images):
hazy = Image.open(hazy_img_path)
clean = Image.open(clean_img_path)
if hazy.size == clean.size:
hazy_ims.append(hazy_img_path)
clean_ims.append(clean_img_path)
self.hazy_images = hazy_ims
self.clean_images = clean_ims
def __getitem__(self, index):
hazy_img = self.rgb_loader(self.hazy_images[index])
clean_img = self.rgb_loader(self.clean_images[index])
hazy_img = self.transform(hazy_img)
clean_img = self.transform(clean_img)
return hazy_img, clean_img
def rgb_loader(self, path):
with open(path, 'rb') as f:
img = Image.open(f)
return img.convert('RGB')
def __len__(self):
return self.size
#Main code for dataloader
hazy_path = "/path/to/train/hazy/images/"
clean_path = "/path/to/train/clean/images/"
transforms = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize([0.485, 0.456, 0.406],[0.229, 0.224, 0.225])
])
dataset = DehazingDataset(hazy_path, clean_path, transform = transforms)
data_loader = data.DataLoader(dataset=dataset,
batch_size=32,
shuffle=True,
num_workers=2)
一旦数据集准备好了,任何图像到图像的翻译模型代码都可以应用到它。