├── image
├── 15.png
└── J.png
├── README.md
├── LICENSE
└── dehaze.py
/image/15.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/He-Zhang/image_dehaze/HEAD/image/15.png
--------------------------------------------------------------------------------
/image/J.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/He-Zhang/image_dehaze/HEAD/image/J.png
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # single image dehaze
2 | ## Introduction
3 | This program implement single image dehazing using dark channel prior.
4 |
5 | ## Compile Dependencies
6 | - OpenCV
7 | - Numpy
8 |
9 | ## Examples
10 |
11 |
12 |
13 |
14 |
15 |
16 | ## Algorithms
17 | - Single Image Haze Removal Using Dark Channel Prior, Kaiming He, Jian Sun, and Xiaoou Tang", in CVPR 2009
18 | - Guided Image Filtering, Kaiming He, Jian Sun, and Xiaoou Tang", in ECCV 2010.
19 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2016 WinCoder
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/dehaze.py:
--------------------------------------------------------------------------------
1 | import cv2;
2 | import math;
3 | import numpy as np;
4 |
5 | def DarkChannel(im,sz):
6 | b,g,r = cv2.split(im)
7 | dc = cv2.min(cv2.min(r,g),b);
8 | kernel = cv2.getStructuringElement(cv2.MORPH_RECT,(sz,sz))
9 | dark = cv2.erode(dc,kernel)
10 | return dark
11 |
12 | def AtmLight(im,dark):
13 | [h,w] = im.shape[:2]
14 | imsz = h*w
15 | numpx = int(max(math.floor(imsz/1000),1))
16 | darkvec = dark.reshape(imsz);
17 | imvec = im.reshape(imsz,3);
18 |
19 | indices = darkvec.argsort();
20 | indices = indices[imsz-numpx::]
21 |
22 | atmsum = np.zeros([1,3])
23 | for ind in range(1,numpx):
24 | atmsum = atmsum + imvec[indices[ind]]
25 |
26 | A = atmsum / numpx;
27 | return A
28 |
29 | def TransmissionEstimate(im,A,sz):
30 | omega = 0.95;
31 | im3 = np.empty(im.shape,im.dtype);
32 |
33 | for ind in range(0,3):
34 | im3[:,:,ind] = im[:,:,ind]/A[0,ind]
35 |
36 | transmission = 1 - omega*DarkChannel(im3,sz);
37 | return transmission
38 |
39 | def Guidedfilter(im,p,r,eps):
40 | mean_I = cv2.boxFilter(im,cv2.CV_64F,(r,r));
41 | mean_p = cv2.boxFilter(p, cv2.CV_64F,(r,r));
42 | mean_Ip = cv2.boxFilter(im*p,cv2.CV_64F,(r,r));
43 | cov_Ip = mean_Ip - mean_I*mean_p;
44 |
45 | mean_II = cv2.boxFilter(im*im,cv2.CV_64F,(r,r));
46 | var_I = mean_II - mean_I*mean_I;
47 |
48 | a = cov_Ip/(var_I + eps);
49 | b = mean_p - a*mean_I;
50 |
51 | mean_a = cv2.boxFilter(a,cv2.CV_64F,(r,r));
52 | mean_b = cv2.boxFilter(b,cv2.CV_64F,(r,r));
53 |
54 | q = mean_a*im + mean_b;
55 | return q;
56 |
57 | def TransmissionRefine(im,et):
58 | gray = cv2.cvtColor(im,cv2.COLOR_BGR2GRAY);
59 | gray = np.float64(gray)/255;
60 | r = 60;
61 | eps = 0.0001;
62 | t = Guidedfilter(gray,et,r,eps);
63 |
64 | return t;
65 |
66 | def Recover(im,t,A,tx = 0.1):
67 | res = np.empty(im.shape,im.dtype);
68 | t = cv2.max(t,tx);
69 |
70 | for ind in range(0,3):
71 | res[:,:,ind] = (im[:,:,ind]-A[0,ind])/t + A[0,ind]
72 |
73 | return res
74 |
75 | if __name__ == '__main__':
76 | import sys
77 | try:
78 | fn = sys.argv[1]
79 | except:
80 | fn = './image/15.png'
81 |
82 | def nothing(*argv):
83 | pass
84 |
85 | src = cv2.imread(fn);
86 |
87 | I = src.astype('float64')/255;
88 |
89 | dark = DarkChannel(I,15);
90 | A = AtmLight(I,dark);
91 | te = TransmissionEstimate(I,A,15);
92 | t = TransmissionRefine(src,te);
93 | J = Recover(I,t,A,0.1);
94 |
95 | cv2.imshow("dark",dark);
96 | cv2.imshow("t",t);
97 | cv2.imshow('I',src);
98 | cv2.imshow('J',J);
99 | cv2.imwrite("./image/J.png",J*255);
100 | cv2.waitKey();
101 |
102 |
--------------------------------------------------------------------------------