本篇博客主要作用为学习代码段与快应用的使用,内容浅显,还请路过的大佬见谅>_<
暗通道去雾算法(Single image haze removal using dark channel prior)可以说是恺明大佬厚积薄发之作,作为其博士期间的第一篇投稿作品,可谓出道即触及巅峰,一举斩获CVPR2009最佳论文奖。
1.论文链接:
Single image haze removal using dark channel prior | IEEE Conference Publication | IEEE Xplorehttps://ieeexplore.ieee.org/document/5206515
2.论文的知识图谱链接:
Connected Papers | Find and explore academic papersConnected Papers is a visual tool to help researchers and applied scientists find academic papers relevant to their field of work.https://www.connectedpapers.com/main/db0fd1d8b1ef0bf19a137cd535166ed067455280/Single-Image-Haze-Removal-Using-Dark-Channel-Prior/graph
3.代码实现:
"""
1.去雾算法介绍博客:
http://blkstone.github.io/2015/08/20/single-image-haze-removal-using-dark-channel/
2.论文地址(2009 CVPR best paper):
https://paperswithcode.com/paper/single-image-haze-removal-using-dark-channel
3.资源下载(镜像)地址:
pip install [The Package You Want to Download] -i https://pypi.tuna.tsinghua.edu.cn/simple
ps. cv2 means opencv-python
"""
import cv2
import numpy as np
import argparse
# 图片相关参数:
# 1.默认图片
defeat_photo = r'..\Input\haze\canon3.bmp'
# 2.待处理图片
photo_name = 'trees.png'
# 3.待处理图片所在目录地址
ImgInput = r'..\Input\haze\{}'.format(photo_name)
# 4.处理后图片保存地址
ImgFile = r'..\Output\HazeRemove'
# 计算雾化图像的暗通道
def DarkChannel(img, size=15):
"""
暗通道的计算主要分成两个步骤:
1.获取BGR三个通道的最小值
2.以一个窗口做MinFilter
ps.这里窗口大小一般为15(radius为7)
获取BGR三个通道的最小值就是遍历整个图像,取最小值即可
"""
r, g, b = cv2.split(img)
min_img = cv2.min(r, cv2.min(g, b))
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (size, size))
dc_img = cv2.erode(min_img, kernel)
return dc_img
# 估算全局大气光值
def GetAtmo(img, percent=0.001):
"""
1.计算有雾图像的暗通道
2.用一个Node的结构记录暗通道图像每个像素的位置和大小,放入list中
3.对list进行降序排序
4.按暗通道亮度前0.1%(用percent参数指定百分比)的位置,在原始有雾图像中查找最大光强值
"""
mean_perpix = np.mean(img, axis=2).reshape(-1)
mean_topper = mean_perpix[:int(img.shape[0] * img.shape[1] * percent)]
return np.mean(mean_topper)
# 估算透射率图
def GetTrans(img, atom, w):
"""
w为去雾程度,一般取0.95
w的值越小,去雾效果越不明显
"""
x = img / atom
t = 1 - w * DarkChannel(x, 15)
return t
def GuidedFilter(p, i, r, e):
"""
:param p: input image
:param i: guidance image
:param r: radius
:param e: regularization
:return: filtering output q
"""
# 1
mean_I = cv2.boxFilter(i, cv2.CV_64F, (r, r))
mean_p = cv2.boxFilter(p, cv2.CV_64F, (r, r))
corr_I = cv2.boxFilter(i * i, cv2.CV_64F, (r, r))
corr_Ip = cv2.boxFilter(i * p, cv2.CV_64F, (r, r))
# 2
var_I = corr_I - mean_I * mean_I
cov_Ip = corr_Ip - mean_I * mean_p
# 3
a = cov_Ip / (var_I + e)
b = mean_p - a * mean_I
# 4
mean_a = cv2.boxFilter(a, cv2.CV_64F, (r, r))
mean_b = cv2.boxFilter(b, cv2.CV_64F, (r, r))
# 5
q = mean_a * i + mean_b
return q
# 去雾主程序
def DeHaze():
path, output, photo, t0, w = opt.input, opt.output, opt.photo, opt.threshold_value, opt.dehaze_degree
# 读取待处理图像
im = cv2.imread(path)
# 压缩RGB通道值于0到1
img = im.astype('float64') / 255
img_gray = cv2.cvtColor(im, cv2.COLOR_BGR2GRAY).astype('float64') / 255
atom = GetAtmo(img)
trans = GetTrans(img, atom, w)
trans_guided = GuidedFilter(trans, img_gray, 20, 0.0001)
"""
1.t0 最小透射率值,一般取0.25
2.投射图t 的值过小——>图像会整体向白场过度
3.因此一般设置一阈值t0:当t值小于t0时,令t=t0
"""
trans_guided = cv2.max(trans_guided, t0)
result = np.empty_like(img)
for i in range(3):
result[:, :, i] = (img[:, :, i] - atom) / trans_guided + atom
# 显示&保存结果
cv2.imshow("source", img)
cv2.imshow("result", result)
cv2.waitKey()
if output is not None:
cv2.imwrite("{}/{}".format(output, photo), result * 255)
# 可通过命令行传递参数
parser = argparse.ArgumentParser()
parser.add_argument('-i', '--input', default=ImgInput)
parser.add_argument('-o', '--output', default=ImgFile)
parser.add_argument('-p', '--photo', default=photo_name)
#t为最小透射率,一般取0.25。投射图t 的值过小——>图像会整体向白场过度
parser.add_argument('-t', '--threshold_value', default=0.25)
#w为去雾程度,一般取0.95。w的值越大,去雾效果越明显
parser.add_argument('-w', '--dehaze_degree', default=0.95)
opt = parser.parse_args()
print(f'parser.parse_args(解析器的参数):\n{opt}')
# 执行主程序
if __name__ == '__main__':
if opt.input is None:
DeHaze(defeat_photo)
else:
DeHaze()
4.1检测效果:
4.2项目代码(pycharm):