대학원 일기

Dark Channel Prior 코드 구현 본문

Paper/Paper codes

Dark Channel Prior 코드 구현

대학원생(노예) 2022. 2. 23. 20:04

Dark Channel Prior

  Dark Channel Prior(이하 DCP)는 단일 이미지 안개제거 기법으로 2009년에 "Single image haze removal using dark channel prior"라는 논문으로 발표되었다. DCP는 안개가 제거된 영상에서 빛의 3원색인 R, G, B 값 중 한 채널이 낮은 수치를 가진다는 통계적 특성으로 이를 활용하여 안개를 제거한다. DCP의 안개제거식은 다음과 같다.

위 식에서 $I(x)$는 안개 영상이고, $J(x)$는 맑은 영상이고, $A$는 안개값(안개가 있는 정도)이다. $e^{-\beta d(x)}$는 빛이 전달되는 양이고, $\beta$는 대기산란계수, $d(x)$는 깊이 정보이다. DCP는 위 식을 기반으로 하여 안개가 제거된 영상을 얻는다.

 

DCP 코드

import os
import cv2
import math
import numpy as np
# https://github.com/He-Zhang/image_dehaze/blob/master/dehaze.py

# Defined Dark Channel
def DarkChannel(img, size): # img: Haze image, size: kernel size
    b, g, r = cv2.split(img) 
    
    dark_channel = cv2.min(cv2.min(r, g), b)  # r,g,b 채널 중 최소값(dark channel) 
    # 안개가 제거된 영상에서 r,g,b 중 한 채널은 낮은 값을 가짐
        
    # cv2.getStructuringElement: 커널과 같은 역할을 하는 구조화 요소, cv2.MORPH_RECT: 직사각형 커널 모양
    kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (size, size))

    # 침식(Erosion): 기존 객체의 영역을 깎아 내는 연산으로 객체 크기가 감소
    dark = cv2.erode(dark_channel, kernel)

    return dark

# Estimate AtmLight(안개값 추정)
# Automatically estimate the atmospheric lights
def AtmLight(img, dark): 
    '''
    1. dark channel에서 가장 밝은 0.1%의 픽셀을 선택(Haze 농도 심한 곳)
    2. 선택한 픽셀 위치에서 input image(I) 중 명도(intensity)가 가장 높은 화소를 Atmospheric light로 선택
    -> 이를 automatically method 라고 함.
    '''
    [h, w] = img.shape[:2] 
    img_size = h*w  
    numpx = int(max(math.floor(img_size/1000), 1)) 
    
    # Vector data(1d)
    darkvec = dark.reshape(img_size) 
    imgvec = img.reshape(img_size, 3) 

    indices = darkvec.argsort() 
    indices = indices[img_size-numpx::] 
    
    atmsum = np.zeros([1, 3]) # r,g,b channel
    for ind in range(0, numpx): 
       atmsum = atmsum + imgvec[indices[ind]] 

    A = atmsum / numpx
    return A 

# Estimate Transmission(전달량 추정)
def TransmissionEstimate(img, A, size): # Haze image, 안개값, kernel size
    omega = 0.95 # 약간의 haze는 남겨야 함(논문 왈: 안개가 너무 완벽히 제거되면 어색하다)
    im3 = np.empty(img.shape, img.dtype) 

    for ind in range(0, 3): 
        im3[:, :, ind] = img[:, :, ind]/A[0, ind] # t = min_c(min_om(Haze image / A))

    transmission = 1 - omega*DarkChannel(im3, size) 
    return transmission

def TransmissionRefine(img, et): # Haze image, transmission
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) 
    gray = np.float64(gray)/255
    
    # Guided Filter
    r = 60 # patch size
    eps = 0.0001 
    t = Guidedfilter(gray, et, r, eps)

    return t

def Guidedfilter(image, p, r, eps): # Haze image(Guide, I), transmission(input), kernel size, strength
    blur_factor = (r, r)
    
    mean_I = cv2.blur(image, blur_factor) # I blurring
    mean_p = cv2.blur(p, blur_factor) # p blurring
    corr_I = cv2.blur(image*image, blur_factor) # I * I blurring
    corr_Ip = cv2.blur(image*p, blur_factor) # I * p blurring

    var_I = corr_I - mean_I * mean_I # variance
    cov_Ip = corr_Ip - mean_I * mean_p # covariance

    a = cov_Ip / (var_I + eps) # 상관계수
    b = mean_p - a * mean_I

    mean_a = cv2.blur(a, blur_factor)
    mean_b = cv2.blur(b, blur_factor)

    q = mean_a * image + mean_b # linear transformation
    return q

def Recover(img, t, A, tx=0.1): # Haze image, transmission, A, tx(A small certain amount of haze are preserved in very dense haze regions)
    res = np.empty(img.shape, img.dtype)
    t = cv2.max(t, tx) 
    
    for ind in range(0, 3):
        res[:, :, ind] = (img[:, :, ind]-A[0, ind])/t + A[0, ind]

    return res

path = os.path.join('./image/mountains.jpg')
src = cv2.resize(cv2.imread(path), dsize=(0,0), fx=0.5, fy=0.5)
I = src.astype('float64')/255

dark = DarkChannel(I, 15)
A = AtmLight(I, dark)
te = TransmissionEstimate(I, A, 15)
t = TransmissionRefine(src, te) # Guieded Filter
J = Recover(I, t, A, 0.1)

cv2.imshow("Dark", dark)
cv2.imshow("Transmission", te)
cv2.imshow("Refine transmission", t)
cv2.imshow('Original', src)
cv2.imshow('Dehaze image', J)

cv2.imwrite("Dark channel prior/output/Haze.jpg", I*255)
cv2.imwrite("Dark channel prior/output/Dark channel.jpg", dark*255)
cv2.imwrite("Dark channel prior/output/DCP_transmission.jpg", te*255)
cv2.imwrite("Dark channel prior/output/DCP_Refined_transmission.jpg", t*255)
cv2.imwrite("Dark channel prior/output/DCP_Dehaze.jpg", J*255)
cv2.waitKey()

 

 

결과: 안개 이미지에 DCP 적용

안개 이미지
 안개 제거 이미지
Dark channel
transmission

 

 

Reference

https://github.com/He-Zhang/image_dehaze

https://ieeexplore.ieee.org/document/5206515

 

Single image haze removal using dark channel prior

In this paper, we propose a simple but effective image prior - dark channel prior to remove haze from a single input image. The dark channel prior is a kind of statistics of the haze-free outdoor images. It is based on a key observation - most local patche

ieeexplore.ieee.org

 

 

'Paper > Paper codes' 카테고리의 다른 글

Color Attenuation Prior 코드 구현  (0) 2022.04.02
White Channel Prior 코드 구현  (0) 2022.02.24
Comments