数字图像处理:暗通道除雾

雾图模型

$$
I(x)=\mathrm{J}(z)\mathrm{t}(x)+\mathrm{A}(1-\mathrm{t}(x))
$$

  • $I(x)$:待去雾的图像
  • $\mathrm{J}(x)$:无雾图像
  • $\mathrm{A}$:全球大气光成分
  • $\mathrm{t}$:折射率(大气传递系数)

导入所需要的库

from PIL import Image
import numpy as np
import matplotlib.pyplot as plt
import platform
if "Ubuntu" in platform.version():
    plt.rcParams['font.sans-serif'] = ['AR PL UKai CN']
elif "Windows" in platform.platform():
    plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False
%config InlineBackend.figure_formats = ['svg']
%matplotlib inline

打开图片

img = Image.open("air.jpg")
img = img.convert('RGB')
img
png

​转换为arry格式

arr = np.array(img)/255
arr.shape

暗通道定义

$$
\mathrm{J^{dark}(X)}=\min_{y\in \Omega(\mathrm{X})}(\min_{c \in {r,g,b}}\mathrm{J^c}(y))
$$

  • $\mathrm{J^c}$:表示彩色图像的每个通道
  • $\Omega(\mathrm{X})$:表示以像素X为中心的一个窗口

意义:首先求出每个像素RGB分量中的最小值,存入一副和原始图像大小相同的灰度图中,然后再对这幅灰度图进行最小值滤波

最小滤波

def minFilter(image):
    min_image = np.zeros(shape=image.shape, dtype=np.float32)
    for i in range(image.shape[0]):
        for j in range(image.shape[1]):
            min_image[i][j] = np.min(image[i:i+3, j:j+3])
    return min_image

生成暗通道

dark = minFilter(arr.min(2))
plt.axis('off')
plt.imshow(dark, cmap='gray')
plt.show()
svg
暗通道图片

估计参数

tot = dark.shape[0]*dark.shape[1]
a = 1  # 去雾强度
A = np.partition(dark.flatten(), -int(tot*0.001))[-int(tot*0.001)]  # 估计大气光
t = 1-a*dark  # 计算折射率

去雾

arr = arr.transpose(2, 0, 1)
qfog = (arr - A)/t+A
qfog = np.minimum(1, qfog)
qfog = qfog.transpose(1, 2, 0)
arr = arr.transpose(1, 2, 0)
Image.fromarray(np.uint8(qfog/qfog.max()*255))
png
去雾后的图片

对比图

plt.figure(figsize=(11, 20))
plt.subplot(1, 2, 1)
plt.imshow(qfog)
plt.axis('off')
plt.title("处理后")
plt.subplot(1, 2, 2)
plt.title("原图")
plt.imshow(arr)
plt.axis('off')
plt.tight_layout()
plt.show()
svg
去雾前后对比图

EricXia

EricXia

喜欢睡觉,热爱钻研各种问题。