图片去雾

最近看图片去雾挺有意思的,于是乎就研究了一下
转载地址图片去雾
先看一下别人的效果, 感觉还不错

图片去雾
图片去雾
看了一些别人写的算法 于是就收了一下 PYthon的 d代码果然有
这个是MATLAB语言版本的

%%%%暗原色去雾算法是建立在户外自然场景暗通道优先法则的基础上的去雾方法,其实就是解一个方程
%%I(x)=J(x)t(x)+A(1-t(x));其中I(x)是受到雾气污染的图像。J(x)是我们需要求的去雾后的图像
%%t(x)是天空中云层的透射分布率,A是天空的亮度
%暗影去雾算法
% 原始图像
img_name = imread('train.bmp');
I = double(img_name) / 255;
% 获取图像大小
[h,w,c] = size(I);
%去雾系数
w0  = 0.95;
img_size = w * h;
%初始化结果图像
dehaze = zeros(h,w,c);
%初始化暗影通道图像
win_dark = zeros(h,w);
for i=1:h                 
    for j=1:w
        win_dark(i,j)=min(I(i,j,:));%将三个通道中最暗的值赋给dark_I(i,j),显然,三维图变成了二维图
    end
 end
win_dark = ordfilt2(win_dark,1,ones(9,9),'symmetric'); //最小值滤波


%计算大气亮度A,相关原理详见论文“Single Image Haze Removal Using Dark Channel Prior”
dark_channel = win_dark;
A = max(max(dark_channel));
[i,j] = find(dark_channel==A);
i = i(1);
j = j(1);
A = mean(I(i,j,:));
%计算初始的transmission map
transmission = 1 - w0 * win_dark / A;
%用guided filter对trasmission map做soft matting
gray_I = I(:,:,1);%这里gray_I 可以是RGB图像中任何一个通道
p = transmission;
r = 80;
eps = 10^-3;
transmission_filter = guidedfilter(gray_I, p, r, eps);
t0=0.1;
t1 = max(t0,transmission_filter);
for i=1:c
    for j=1:h
        for l=1:w
            dehaze(j,l,i)=(I(j,l,i)-A)/t1(j,l)+A;
        end
    end
end
figure,
imshow(I);title('去雾前')
figure,
imshow(dehaze);title('去雾后')

里面用到的两个函数如下:(这两个函数是何凯明guided filter中的,详细原理可以参考博客园中laviewpb的分析)

function q = guidedfilter(I, p, r, eps)
%   GUIDEDFILTER   O(1) time implementation of guided filter.
%
%   - guidance image: I (should be a gray-scale/single channel image)
%   - filtering input image: p (should be a gray-scale/single channel image)
%   - local window radius: r
%   - regularization parameter: eps


[hei, wid] = size(I);
N = boxfilter(ones(hei, wid), r); % the size of each local patch; N=(2r+1)^2 except for boundary pixels.


mean_I = boxfilter(I, r) ./ N;
mean_p = boxfilter(p, r) ./ N;
mean_Ip = boxfilter(I.*p, r) ./ N;
cov_Ip = mean_Ip - mean_I .* mean_p; % this is the covariance of (I, p) in each local patch.


mean_II = boxfilter(I.*I, r) ./ N;
var_I = mean_II - mean_I .* mean_I;


a = cov_Ip ./ (var_I + eps); % Eqn. (5) in the paper;
b = mean_p - a .* mean_I; % Eqn. (6) in the paper;


mean_a = boxfilter(a, r) ./ N;
mean_b = boxfilter(b, r) ./ N;


q = mean_a .* I + mean_b; % Eqn. (8) in the paper;
end



function imDst = boxfilter(imSrc, r)


%   BOXFILTER   O(1) time box filtering using cumulative sum
%
%   - Definition imDst(x, y)=sum(sum(imSrc(x-r:x+r,y-r:y+r)));
%   - Running time independent of r; 
%   - Equivalent to the function: colfilt(imSrc, [2*r+1, 2*r+1], 'sliding', @sum);
%   - But much faster.


[hei, wid] = size(imSrc);
imDst = zeros(size(imSrc));


%cumulative sum over Y axis
imCum = cumsum(imSrc, 1);
%difference over Y axis
imDst(1:r+1, :) = imCum(1+r:2*r+1, :);
imDst(r+2:hei-r, :) = imCum(2*r+2:hei, :) - imCum(1:hei-2*r-1, :);
imDst(hei-r+1:hei, :) = repmat(imCum(hei, :), [r, 1]) - imCum(hei-2*r:hei-r-1, :);


%cumulative sum over X axis
imCum = cumsum(imDst, 2);
%difference over Y axis
imDst(:, 1:r+1) = imCum(:, 1+r:2*r+1);
imDst(:, r+2:wid-r) = imCum(:, 2*r+2:wid) - imCum(:, 1:wid-2*r-1);
imDst(:, wid-r+1:wid) = repmat(imCum(:, wid), [1, r]) - imCum(:, wid-2*r:wid-r-1);
end

python

# -*- coding: utf-8 -*-
"""
Created on Sat Jun  9 11:28:14 2018

@author: zhxing
"""

import cv2 
import os
import numpy as np  
   
def zmMinFilterGray(src, r=8):  
    '''''最小值滤波,r是滤波器半径'''  
    return cv2.erode(src,np.ones((2*r-1,2*r-1)))
# =============================================================================
#     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)  
   
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.50, 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('s.png')/255.0)*255  
    cv2.imwrite('defoa777g.jpg', m)  
# def scanfdir():
#     path = os.listdir("C:\\Users\\理解\Desktop\\imgtest\\");
#     return path
 
# path = scanfdir()
# for x in path:
#     b = "imgtest\\"+x
#     c = "1\\"+x
#     m = deHaze(cv2.imread(b)/255.0)*255  
#     cv2.imwrite(c, m)