-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathimgpreprocesing.py
108 lines (93 loc) · 5.22 KB
/
imgpreprocesing.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
import cv2
import numpy as np
def correction(
img,
shadow_amount_percent, shadow_tone_percent, shadow_radius,
highlight_amount_percent, highlight_tone_percent, highlight_radius,
color_percent
):
"""
Image Shadow / Highlight Correction. The same function as it in Photoshop / GIMP
:param img: input RGB image numpy array of shape (height, width, 3)
:param shadow_amount_percent [0.0 ~ 1.0]: Controls (separately for the highlight and shadow values in the image) how much of a correction to make.
:param shadow_tone_percent [0.0 ~ 1.0]: Controls the range of tones in the shadows or highlights that are modified.
:param shadow_radius [>0]: Controls the size of the local neighborhood around each pixel
:param highlight_amount_percent [0.0 ~ 1.0]: Controls (separately for the highlight and shadow values in the image) how much of a correction to make.
:param highlight_tone_percent [0.0 ~ 1.0]: Controls the range of tones in the shadows or highlights that are modified.
:param highlight_radius [>0]: Controls the size of the local neighborhood around each pixel
:param color_percent [-1.0 ~ 1.0]:
:return:
"""
shadow_tone = shadow_tone_percent * 255
highlight_tone = 255 - highlight_tone_percent * 255
shadow_gain = 1 + shadow_amount_percent * 6
highlight_gain = 1 + highlight_amount_percent * 6
# extract RGB channel
height, width = img.shape[:2]
img = img.astype(np.float)
img_R, img_G, img_B = img[..., 2].reshape(-1), img[..., 1].reshape(-1), img[..., 0].reshape(-1)
# The entire correction process is carried out in YUV space,
# adjust highlights/shadows in Y space, and adjust colors in UV space
# convert to Y channel (grey intensity) and UV channel (color)
img_Y = .3 * img_R + .59 * img_G + .11 * img_B
img_U = -img_R * .168736 - img_G * .331264 + img_B * .5
img_V = img_R * .5 - img_G * .418688 - img_B * .081312
# extract shadow / highlight
shadow_map = 255 - img_Y * 255 / shadow_tone
shadow_map[np.where(img_Y >= shadow_tone)] = 0
highlight_map = 255 - (255 - img_Y) * 255 / (255 - highlight_tone)
highlight_map[np.where(img_Y <= highlight_tone)] = 0
# // Gaussian blur on tone map, for smoother transition
if shadow_amount_percent * shadow_radius > 0:
# shadow_map = cv2.GaussianBlur(shadow_map.reshape(height, width), ksize=(shadow_radius, shadow_radius), sigmaX=0).reshape(-1)
shadow_map = cv2.blur(shadow_map.reshape(height, width), ksize=(shadow_radius, shadow_radius)).reshape(-1)
if highlight_amount_percent * highlight_radius > 0:
# highlight_map = cv2.GaussianBlur(highlight_map.reshape(height, width), ksize=(highlight_radius, highlight_radius), sigmaX=0).reshape(-1)
highlight_map = cv2.blur(highlight_map.reshape(height, width), ksize=(highlight_radius, highlight_radius)).reshape(-1)
# Tone LUT
t = np.arange(256)
LUT_shadow = (1 - np.power(1 - t * (1 / 255), shadow_gain)) * 255
LUT_shadow = np.maximum(0, np.minimum(255, np.int_(LUT_shadow + .5)))
LUT_highlight = np.power(t * (1 / 255), highlight_gain) * 255
LUT_highlight = np.maximum(0, np.minimum(255, np.int_(LUT_highlight + .5)))
# adjust tone
shadow_map = shadow_map * (1 / 255)
highlight_map = highlight_map * (1 / 255)
iH = (1 - shadow_map) * img_Y + shadow_map * LUT_shadow[np.int_(img_Y)]
iH = (1 - highlight_map) * iH + highlight_map * LUT_highlight[np.int_(iH)]
img_Y = iH
# adjust color
if color_percent != 0:
# color LUT
if color_percent > 0:
LUT = (1 - np.sqrt(np.arange(32768)) * (1 / 128)) * color_percent + 1
else:
LUT = np.sqrt(np.arange(32768)) * (1 / 128) * color_percent + 1
# adjust color saturation adaptively according to highlights/shadows
color_gain = LUT[np.int_(img_U ** 2 + img_V ** 2 + .5)]
w = 1 - np.minimum(2 - (shadow_map + highlight_map), 1)
img_U = w * img_U + (1 - w) * img_U * color_gain
img_V = w * img_V + (1 - w) * img_V * color_gain
# re convert to RGB channel
output_R = np.int_(img_Y + 1.402 * img_V + .5)
output_G = np.int_(img_Y - .34414 * img_U - .71414 * img_V + .5)
output_B = np.int_(img_Y + 1.772 * img_U + .5)
output = np.row_stack([output_B, output_G, output_R]).T.reshape(height, width, 3)
output = np.minimum(output, 255).astype(np.uint8)
return output
def preprocessing(image):
arrayCorrection = correction(image, shadow_amount_percent=1, shadow_tone_percent=1, shadow_radius=20, highlight_amount_percent=0.2, highlight_tone_percent=0.2, highlight_radius=10, color_percent=0)
imgCorrection = np.array(arrayCorrection)
gray = cv2.cvtColor(imgCorrection,cv2.COLOR_RGB2GRAY)
blur = cv2.GaussianBlur(gray,(1,1),0)
denoise = cv2.fastNlMeansDenoising(blur,None,10,7,21)
hist = cv2.equalizeHist(denoise)
gamma = 0.2
invGamma = 1/gamma
table = np.array([((i/255.0)**invGamma)*255
for i in np.arange(0,256)]).astype("uint8")
gamm = cv2.LUT(hist,table,hist)
ret, thresh = cv2.threshold(gamm
,0,255,cv2.THRESH_OTSU + cv2.THRESH_BINARY_INV)
hasilPreprocessingRGB = cv2.cvtColor(thresh,cv2.COLOR_GRAY2RGB)
return hasilPreprocessingRGB