|
- """
- /**
- * Copyright 2020 Zhejiang Lab. All Rights Reserved.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * =============================================================
- */
- Reference:
- - [Single Image Haze Removal Using Dark Channel Prior]
- (http://kaiminghe.com/publications/cvpr09.pdf) (CVPR 2009)
- """
- # !/usr/bin/env python
- # -*- coding:utf-8 -*-
- import cv2
- import numpy as np
-
-
- def guidedFilter(I, p, r, eps):
- """The implementation of guide filter
- Args:
- I: Guide image
- p: Input image
- r: The radius of filter window
- eps: Regularization parameter
- Returns:
- re: The result of guide filter
- """
- mean_I = cv2.boxFilter(I, -1, (r, r))
- mean_p = cv2.boxFilter(p, -1, (r, r))
- mean_Ip = cv2.boxFilter(I * p, -1, (r, r))
- cov_Ip = mean_Ip - mean_I * mean_p
-
- mean_II = cv2.boxFilter(I * I, -1, (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, -1, (r, r))
- mean_b = cv2.boxFilter(b, -1, (r, r))
- re = mean_a * I + mean_b
- return re
-
-
- def AtmLight(img, TR, bins=2000):
- """Get the global atmospheric light of input image
- Args:
- img: Input image
- TR: The refined atmospheric mask image
- bins: The number of equal-width bins in the given range
- Returns:
- A: The global atmospheric light of input image
- """
- ht = np.histogram(TR, bins)
- d = np.cumsum(ht[0]) / float(TR.size)
- try:
- lmax = next(y for y in range(len(d) - 1, 0, -1) if d[y] <= 0.999)
- except:
- lmax = 1
- A = np.mean(img, 2)[TR >= ht[1][lmax]].max()
- return A
-
-
- def TransRefine(img, radius, eps, dehaze_ratio, maxTR):
- """Get the refined atmospheric mask image
- Args:
- img: Input image
- radius: The radius of filter window for guide filter
- eps: The radius of filter window for guide filter
- dehaze_ratio: the ratio of dehaze
- maxTR: The limitation of the output
- Returns:
- TR: The refined atmospheric mask image
- """
- h, w = img.shape[:2]
- img = cv2.pyrDown(img, (w // 4, h // 4))
- TR = np.min(img, 2)
- filter_TR = cv2.erode(TR, np.ones((2 * radius + 1, 2 * radius + 1)))
- TR = guidedFilter(TR, filter_TR, radius, eps)
- TR = cv2.resize(TR, (w, h))
- TR = np.minimum(TR * dehaze_ratio, maxTR)
- return TR
-
-
- def deHaze(
- img,
- radius=81,
- eps=0.001,
- dehaze_ratio=0.95,
- maxTR=0.80):
- re = np.zeros(img.shape)
- TR = TransRefine(img, radius, eps, dehaze_ratio, maxTR)
- A = AtmLight(img, TR, bins=2000)
- for k in range(3):
- re[:, :, k] = (img[:, :, k] - TR) / (1 - TR / A)
- re = np.clip(re, 0, 1)
- return re
-
-
- def addHaze(img, radius=81, eps=0.001, dehaze_ratio=0.95, maxTR=0.80):
- re = np.zeros(img.shape)
- TR = TransRefine(img, radius, eps, dehaze_ratio, maxTR)
- A = AtmLight(img, TR, bins=2000)
- for k in range(3):
- re[:, :, k] = (img[:, :, k] * 0.7) + A * 0.3
- re = np.clip(re, 0, 1)
- return re
|