暗通道去霧算法的python實現


    何凱明博士的去霧文章和算法實現已經漫天飛了,我今天也就不啰里啰唆,直接給出自己python實現的完整版本,全部才60多行代碼,簡單易懂,並有簡要注釋,去霧效果也很不錯。

    在這個python版本中,計算量最大的就是最小值濾波,純python寫的,慢,可以進一步使用C優化,其他部分都是使用numpy和opencv的現成東東,效率還行。

import cv2
import numpy as np
 
def zmMinFilterGray(src, r=7):
    '''最小值濾波,r是濾波器半徑'''
    '''if r <= 0:
        return src
    h, w = src.shape[:2]
    I = src
    res = np.minimum(I  , I[[0]+range(h-1)  , :])
    res = np.minimum(res, I[range(1,h)+[h-1], :])
    I = res
    res = np.minimum(I  , I[:, [0]+range(w-1)])
    res = np.minimum(res, I[:, range(1,w)+[w-1]])
    return zmMinFilterGray(res, r-1)'''
    return cv2.erode(src, np.ones((2*r+1, 2*r+1)))                      #使用opencv的erode函數更高效
def guidedfilter(I, p, r, eps):
    '''引導濾波,直接參考網上的matlab代碼'''
    height, width = I.shape
    m_I = cv2.boxFilter(I, -1, (r,r))
    m_p = cv2.boxFilter(p, -1, (r,r))
    m_Ip = cv2.boxFilter(I*p, -1, (r,r))
    cov_Ip = m_Ip-m_I*m_p
 
    m_II = cv2.boxFilter(I*I, -1, (r,r))
    var_I = m_II-m_I*m_I
 
    a = cov_Ip/(var_I+eps)
    b = m_p-a*m_I
 
    m_a = cv2.boxFilter(a, -1, (r,r))
    m_b = cv2.boxFilter(b, -1, (r,r))
    return m_a*I+m_b
 
def getV1(m, r, eps, w, maxV1):  #輸入rgb圖像,值范圍[0,1]
    '''計算大氣遮罩圖像V1和光照值A, V1 = 1-t/A'''
    V1 = np.min(m,2)                                         #得到暗通道圖像
    V1 = guidedfilter(V1, zmMinFilterGray(V1,7), r, eps)     #使用引導濾波優化
    bins = 2000
    ht = np.histogram(V1, bins)                              #計算大氣光照A
    d = np.cumsum(ht[0])/float(V1.size)
    for lmax in range(bins-1, 0, -1):
        if d[lmax]<=0.999:
            break
    A  = np.mean(m,2)[V1>=ht[1][lmax]].max()
         
    V1 = np.minimum(V1*w, maxV1)                   #對值范圍進行限制
     
    return V1,A
 
def deHaze(m, r=81, eps=0.001, w=0.95, maxV1=0.80, bGamma=False):
    Y = np.zeros(m.shape)
    V1,A = getV1(m, r, eps, w, maxV1)               #得到遮罩圖像和大氣光照
    for k in range(3):
        Y[:,:,k] = (m[:,:,k]-V1)/(1-V1/A)           #顏色校正
    Y =  np.clip(Y, 0, 1)
    if bGamma:
        Y = Y**(np.log(0.5)/np.log(Y.mean()))       #gamma校正,默認不進行該操作
    return Y
 
if __name__ == '__main__':
    m = deHaze(cv2.imread('land.jpg')/255.0)*255
    cv2.imwrite('defog.jpg', m)

  

下面給兩個運行效果吧

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM