美文网首页
图像去雾算法

图像去雾算法

作者: Byte猫 | 来源:发表于2019-05-21 17:19 被阅读0次

    雾霾是由空气中的灰尘和烟雾等小的漂浮颗粒产生的常见大气现象。这些漂浮的颗粒极大地吸收和散射光,导致图像质量下降。在雾霾影响下,视频监控,远程感应,自动驾驶等许多实际应用很容易受到威胁,检测和识别等高级计算机视觉任务很难完成。因此,图像去雾(除雾)成为一种越来越重要的技术。

    暗通道去雾算法

    Kaiming(何凯明)早在09年以MSRA实习生的身份发布的Single Image Haze Removal Using Dark Channel Prior获得CVPR best paper,其内容就是给图像去雾。当时并没有用深度学习,却能实现让人震惊的效果。

    1、雾图模型

    计算机视觉中,下面这个雾图形成模型是被广泛使用的:



    其中I(x)是现有的图像(待去雾),J(x)是要恢复的原无雾图像,A是全球大气光成分,t(x)是大气折射率。
    变形可得:


    2、暗通道与折射率预估

    所谓暗通道是一个基本假设,这个假设认为,在绝大多数的非天空的局部区域中,某一些像素总会有至少一个颜色通道具有很低的值。这个其实很容易理解,实际生活中造成这个假设的原因有很多,比如汽车,建筑物或者城市中的阴影,或者说色彩鲜艳的物体或表面(比如绿色的树叶,各种鲜艳的花,或者蓝色绿色的睡眠),颜色较暗的物体或者表面,这些景物的暗通道总是变现为比较暗的状态。
    我们来看一下有雾图像和无雾图像暗通道的区别:




    可以发现,有雾的时候会呈现一定的灰色,而无雾的时候则会呈现大量的黑色(像素为接近0)。
    所以暗通道是什么呢?其实比较简单,作者认为暗通道是:



    暗通道先验理论指出:

    由此可以用于预估折射率

    但是现实生活中,即使是晴天白云,空气中也会存在一些颗粒,看远方的物体还是能够感觉到雾的影响,另外,雾的存在可以让人们感觉到景深的存在,所以我们保留一部分的雾,上式修正为:



    其中w是[0-1]之间的一个值,一般取0.95差不多。

    3、计算全球大气光

    现在唯一未知的就是全球大气光A了。实际中,我们可以借助暗通道图来从有雾图像中来获取该值:
    第一步,从暗通道图中按照亮度大小取前0.1%的像素。
    第二步,在这些位置中,在原始图像中寻找对应具有最高亮度点的值,作为A值。

    4、代码实现

    # coding=utf-8
    import numpy as np
    from PIL import Image
    import cv2 as cv
    import matplotlib.pyplot as plt
    import math
    
    def guidedfilter(I, p, r, eps):
        '''
        引导滤波
        '''
        height, width = I.shape
        m_I = cv.boxFilter(I, -1, (r,r))
        m_p = cv.boxFilter(p, -1, (r,r))
        m_Ip = cv.boxFilter(I*p, -1, (r,r))
        cov_Ip = m_Ip-m_I*m_p
      
        m_II = cv.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 = cv.boxFilter(a, -1, (r,r))
        m_b = cv.boxFilter(b, -1, (r,r))
        return m_a*I+m_b
    
    def get_dc_A(I, r, eps, w, maxGray):
        '''
        计算暗通道图dc和光照值A:V1 = 1-t/A
        INPUT -> 归一化图像数组, 滤波器半径, 噪声, 灰度范围, maxGray
        '''
        # 分离三通道
        B,G,R = cv.split(I)
        # 求出每个像素RGB分量中的最小值, 得到暗通道图
        dc = cv.min(cv.min(R,G), B)
        # 使用引导滤波优化
        dc = guidedfilter(dc, cv.erode(dc, np.ones((2*r+1, 2*r+1))), r, eps)
        bins = 2000
        # 计算大气光照A
        ht = np.histogram(dc, bins)
        d = np.cumsum(ht[0])/float(dc.size)
        for lmax in range(bins-1, 0, -1):
            if d[lmax]<=0.999:
                break
        A  = np.mean(I, 2)[dc>=ht[1][lmax]].max()
        # 对值范围进行限制
        dc = np.minimum(dc*w, maxGray)
        return dc, A
    
    if __name__ == '__main__':
        src = np.array(Image.open('231.jpg'))
        I = src.astype('float64')/255
        
        # 得到遮罩图像和大气光照
        dc, A = get_dc_A(I, 111, 0.001, 0.95, 0.80)
        # 调用雾图模型
        J = np.zeros(I.shape)
        for k in range(3):
            J[:,:,k] = (I[:,:,k]-dc)/(1-dc/A)
        J =  np.clip(J, 0, 1)
        # 伽马校正
        J = J**(np.log(0.5)/np.log(J.mean()))
        # 拼接结果
        output = np.hstack((I, J))
        plt.imshow(Image.fromarray(np.uint8(output*255)))
        plt.show()
    

    相关文章

      网友评论

          本文标题:图像去雾算法

          本文链接:https://www.haomeiwen.com/subject/qnojzqtx.html