-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathocean_enhance.py
121 lines (87 loc) · 3.09 KB
/
ocean_enhance.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
import numpy as np
import cv2
def resize(img, perc=0.5):
"""Utility function to resize the image"""
width = int(img.shape[1] * perc)
height = int(img.shape[0] * perc)
resized = cv2.resize(img, (width, height), interpolation=cv2.INTER_AREA)
return resized
def dark_channel(img, sz=15):
"""Calculates the dark channel in step 1"""
b, g, r = cv2.split(img)
dc = r - cv2.max(b, g)
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (sz, sz))
dark = cv2.erode(dc, kernel)
return dark
def airlight(img, dc):
"""Calculates the air-light in step 4"""
[h, w] = img.shape[:2]
imgsz = h * w
imgvec = img.reshape(imgsz, 3)
dcvec = dc.reshape(imgsz)
indices = dcvec.argsort()
return imgvec[indices[0]]
def transmission_estimate(dc):
"""Calculates the transmission map as mentioned in step 2"""
te = dc + (1 - np.max(dc))
return te
def guided_filter(img, p, r, eps):
"""Helper function to refine the transmission"""
mean_I = cv2.boxFilter(img, cv2.CV_64F, (r, r))
mean_p = cv2.boxFilter(p, cv2.CV_64F, (r, r))
mean_Ip = cv2.boxFilter(img * p, cv2.CV_64F, (r, r))
cov_Ip = mean_Ip - mean_I * mean_p
mean_II = cv2.boxFilter(img * img, cv2.CV_64F, (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, cv2.CV_64F, (r, r))
mean_b = cv2.boxFilter(b, cv2.CV_64F, (r, r))
q = mean_a * img + mean_b
return q
def transmission_refine(img, et):
"""Refines the transmission map as mentioned in step 3"""
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
gray = np.float64(gray) / 255
r = 60
eps = 0.0001
t = guided_filter(gray, et, r, eps)
return t
def recover(img, t, A):
"""Finally recovers the image using the image, the transmission map and air-light"""
res = np.empty(img.shape, img.dtype)
for index in range(0, 3):
res[:, :, index] = (img[:, :, index] - A[index]) / t + A[index]
return res
def normalize_image(img):
"""Utility function to normalize the intensities of the pixels in the image"""
img = img - img.min()
img = img / img.max() * 255
img = np.uint8(img)
return img
def dummy(x):
pass
if __name__ == '__main__':
filename = 'table.png'
scale = 1
src = cv2.imread(f'image/ocean_input/{filename}')
src = resize(src, scale)
img = src.astype('float64') / 255
cv2.namedWindow('controls')
cv2.createTrackbar('ksize', 'controls', 1, 600, dummy)
while True:
ksize = int(cv2.getTrackbarPos('ksize', 'controls')) + 1
dc = dark_channel(img, ksize)
te = transmission_estimate(dc)
tr = transmission_refine(src, te)
A = airlight(img, tr)
result = recover(img, tr, A)
result = normalize_image(result)
cv2.imshow('Transmission estimate', te)
cv2.imshow('Transmission refined', tr)
cv2.imshow('Input', img)
cv2.imshow('Result', result)
k = cv2.waitKey(1) & 0xFF
if k == 27:
break
cv2.imwrite(f'image/ocean_output/{filename}', result)