Python图像处理丨详解图像去雾处理方法( 六 )


文章插图
 

Python图像处理丨详解图像去雾处理方法

文章插图
 
(4) 公式变形
根据大气散射模型,将第一个公式稍作处理,变形为下式:
Python图像处理丨详解图像去雾处理方法

文章插图
 
假设每一个窗口的透射率t(x)为常数,记为t’(x),并且A值已给定,对式两边同时进行两次最小值运算,可得:
Python图像处理丨详解图像去雾处理方法

文章插图
 
其中,J(x)是要求的无雾图像,根据前述的暗通道先验理论可知:
Python图像处理丨详解图像去雾处理方法

文章插图
 
因此可推导出:
Python图像处理丨详解图像去雾处理方法

文章插图
 
(5) 透射率计算
将上式带入可得到透射率t’(x)的预估值,如下所示:
Python图像处理丨详解图像去雾处理方法

文章插图
 
现实生活中,即便晴空万里,空气中也会存在一些颗粒,在眺望远处的景物时,人们还是能感觉到雾的存在 。另外,雾的存在让人们感受到景深,因此在去雾的同时有必要保留一定程度的雾 。可以通过引入一个0到1之 间 的 因 子 w(一 般取0.95)对预估透射率进行修正,如式所示:
Python图像处理丨详解图像去雾处理方法

文章插图
 
以上的推导过程均假设大气光值A是已知的,在实际中,可以借助暗通道图从原始雾图中求取 。具体步骤如下:
 
  • 先求取暗通道图,在暗通道图中按照亮度的大小提取最亮的前0.1%的像素
  • 在原始雾图I(x)中找对应位置上具有最高亮度的点的值,作为大气光值A
 
此外,由于透射率t偏小时,会造成J偏大,恢复的无雾图像整体向白场过度,因此有必要对透射率设置一个下限值t0(一般取值为0.1),当t值小于t0 时,取t=t0 。将以上求得的透射率和大气光值代入公式,最终整理得到图像的恢复公式如下:
Python图像处理丨详解图像去雾处理方法

文章插图
 
这就是暗通道先验去雾算法的原理过程,下面简单补充论文中的处理效果图 。
Python图像处理丨详解图像去雾处理方法

文章插图
 
再次膜拜偶像,极力推荐大家阅读论文 。
2.算法实现
实现代码引用木老师的,感觉比我写得好,参考如下:
 
  • openCV+python实现图像去雾 - 木盏老师
# -*- coding: utf-8 -*- """ Created on Sat Sep 11 00:16:07 2021 @author: xiuzhang 参考资料: https://blog.csdn.net/leviopku/article/details/83898619 """ import sys import cv2 import math import numpy as np def DarkChannel(im,sz): b,g,r = cv2.split(im) dc = cv2.min(cv2.min(r,g),b) kernel = cv2.getStructuringElement(cv2.MORPH_RECT,(sz,sz)) dark = cv2.erode(dc,kernel) return dark def AtmLight(im,dark): [h,w] = im.shape[:2] imsz = h*w numpx = int(max(math.floor(imsz/1000),1)) darkvec = dark.reshape(imsz,1) imvec = im.reshape(imsz,3) indices = darkvec.argsort() indices = indices[imsz-numpx::] atmsum = np.zeros([1,3]) for ind in range(1,numpx): atmsum = atmsum + imvec[indices[ind]] A = atmsum / numpx; return A def TransmissionEstimate(im,A,sz): omega = 0.95 im3 = np.empty(im.shape,im.dtype) for ind in range(0,3): im3[:,:,ind] = im[:,:,ind]/A[0,ind] transmission = 1 - omega*DarkChannel(im3,sz) return transmission def Guidedfilter(im,p,r,eps): mean_I = cv2.boxFilter(im,cv2.CV_64F,(r,r)) mean_p = cv2.boxFilter(p, cv2.CV_64F,(r,r)) mean_Ip = cv2.boxFilter(im*p,cv2.CV_64F,(r,r)) cov_Ip = mean_Ip - mean_I*mean_p mean_II = cv2.boxFilter(im*im,cv2.CV_64F,(r,r)) var_I = mean_II - mean_I*mean_I a = cov_Ip/(var_I + eps) b = mean_p - a*mean_I mean_a = cv2.boxFilter(a,cv2.CV_64F,(r,r)) mean_b = cv2.boxFilter(b,cv2.CV_64F,(r,r)) q = mean_a*im + mean_b return q def TransmissionRefine(im,et): gray = cv2.cvtColor(im,cv2.COLOR_BGR2GRAY) gray = np.float64(gray)/255 r = 60 eps = 0.0001 t = Guidedfilter(gray,et,r,eps) return t def Recover(im,t,A,tx = 0.1): res = np.empty(im.shape,im.dtype) t = cv2.max(t,tx) for ind in range(0,3): res[:,:,ind] = (im[:,:,ind]-A[0,ind])/t + A[0,ind] return res if __name__ == '__main__': fn = 'car-02.png' src = https://www.isolves.com/it/cxkf/yy/Python/2022-12-30/cv2.imread(fn) I = src.astype('float64')/255 dark = DarkChannel(I,15) A = AtmLight(I,dark) te = TransmissionEstimate(I,A,15) t = TransmissionRefine(src,te) J = Recover(I,t,A,0.1) arr = np.hstack((I, J)) cv2.imshow("contrast", arr) cv2.imwrite("car-02-dehaze.png", J*255 ) cv2.imwrite("car-02-contrast.png", arr*255) cv2.waitKey();


推荐阅读