Spaces:
Running
Running
- Syn_img_lowlight_withnoise.h5 +3 -0
- app.py +74 -0
- requirements.txt +4 -0
- utls.py +124 -0
Syn_img_lowlight_withnoise.h5
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:40fa63cc1bfa1a072f3aa962b35710498de7d7d7f4a533cdea228ac573f70411
|
3 |
+
size 2049408
|
app.py
ADDED
@@ -0,0 +1,74 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import os
|
2 |
+
import time
|
3 |
+
import logging
|
4 |
+
import numpy as np
|
5 |
+
import keras.optimizers
|
6 |
+
import cv2
|
7 |
+
import gradio as gr
|
8 |
+
import Network
|
9 |
+
import utls
|
10 |
+
|
11 |
+
class ImageProcessor:
|
12 |
+
|
13 |
+
def __init__(self, model_name):
|
14 |
+
self.model_name = model_name
|
15 |
+
self.mbllen = Network.build_mbllen((None, None, 3))
|
16 |
+
self.mbllen.load_weights(f'{model_name}.h5')
|
17 |
+
self.opt = keras.optimizers.Adam(lr=2 * 1e-04, beta_1=0.9, beta_2=0.999, epsilon=1e-08)
|
18 |
+
self.mbllen.compile(loss='mse', optimizer=self.opt)
|
19 |
+
|
20 |
+
def process_image(self, image, highpercent, lowpercent, gamma, maxrange):
|
21 |
+
img_A = np.array(image) / 255.0
|
22 |
+
img_A = img_A[np.newaxis, :]
|
23 |
+
|
24 |
+
maxrange /= 10.
|
25 |
+
hsvgamma = gamma / 10.
|
26 |
+
|
27 |
+
out_pred = self.mbllen.predict(img_A)
|
28 |
+
|
29 |
+
fake_B = out_pred[0, :, :, :3]
|
30 |
+
fake_B = self.adjust_image(fake_B, maxrange, highpercent, lowpercent, hsvgamma)
|
31 |
+
|
32 |
+
return fake_B
|
33 |
+
|
34 |
+
def adjust_image(self, fake_B, maxrange, highpercent, lowpercent, hsvgamma):
|
35 |
+
gray_fake_B = fake_B[:, :, 0] * 0.299 + fake_B[:, :, 1] * 0.587 + fake_B[:, :, 1] * 0.114
|
36 |
+
percent_max = sum(sum(gray_fake_B >= maxrange)) / sum(sum(gray_fake_B <= 1.0))
|
37 |
+
max_value = np.percentile(gray_fake_B[:], highpercent)
|
38 |
+
if percent_max < (100-highpercent)/100.:
|
39 |
+
scale = maxrange / max_value
|
40 |
+
fake_B = fake_B * scale
|
41 |
+
fake_B = np.minimum(fake_B, 1.0)
|
42 |
+
|
43 |
+
gray_fake_B = fake_B[:,:,0]*0.299 + fake_B[:,:,1]*0.587 + fake_B[:,:,1]*0.114
|
44 |
+
sub_value = np.percentile(gray_fake_B[:], lowpercent)
|
45 |
+
fake_B = (fake_B - sub_value) * (1./(1-sub_value))
|
46 |
+
|
47 |
+
imgHSV = cv2.cvtColor(fake_B, cv2.COLOR_RGB2HSV)
|
48 |
+
H, S, V = cv2.split(imgHSV)
|
49 |
+
S = np.power(S, hsvgamma)
|
50 |
+
imgHSV = cv2.merge([H, S, V])
|
51 |
+
fake_B = cv2.cvtColor(imgHSV, cv2.COLOR_HSV2RGB)
|
52 |
+
fake_B = np.minimum(fake_B, 1.0)
|
53 |
+
|
54 |
+
return fake_B
|
55 |
+
|
56 |
+
if __name__ == "__main__":
|
57 |
+
logging.basicConfig(filename='image_processor.log', level=logging.INFO)
|
58 |
+
|
59 |
+
image_processor = ImageProcessor(model_name='Syn_img_lowlight_withnoise')
|
60 |
+
iface = gr.Interface(
|
61 |
+
image_processor.process_image,
|
62 |
+
[
|
63 |
+
gr.inputs.Image(shape=(None, None)), # Corrected line
|
64 |
+
gr.inputs.Slider(85, 100, default=95, label="High Percent"),
|
65 |
+
gr.inputs.Slider(0, 100, default=5, label="Low Percent"),
|
66 |
+
gr.inputs.Slider(6, 10, default=8, label="Gamma"),
|
67 |
+
gr.inputs.Slider(0, 20, default=8, label="Max Range"),
|
68 |
+
],
|
69 |
+
gr.outputs.Image(type="numpy"),
|
70 |
+
)
|
71 |
+
|
72 |
+
|
73 |
+
|
74 |
+
iface.launch(debug=True,share=True)
|
requirements.txt
ADDED
@@ -0,0 +1,4 @@
|
|
|
|
|
|
|
|
|
|
|
1 |
+
Tensorflow==1.6.0
|
2 |
+
Keras==2.2.0
|
3 |
+
Opencv-python==3.4.2
|
4 |
+
logging
|
utls.py
ADDED
@@ -0,0 +1,124 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import tensorflow as tf
|
2 |
+
from keras import backend as K
|
3 |
+
import numpy as np
|
4 |
+
import scipy
|
5 |
+
import os
|
6 |
+
import cv2 as cv
|
7 |
+
|
8 |
+
def bright_mae(y_true, y_pred):
|
9 |
+
return K.mean(K.abs(y_pred[:,:,:,:3] - y_true[:,:,:,:3]))
|
10 |
+
|
11 |
+
def bright_mse(y_true, y_pred):
|
12 |
+
return K.mean((y_pred[:,:,:,:3] - y_true[:,:,:,:3])**2)
|
13 |
+
|
14 |
+
def bright_AB(y_true, y_pred):
|
15 |
+
return K.abs(K.mean(y_true[:,:,:,:3])-K.mean(y_pred[:,:,:,:3]))
|
16 |
+
|
17 |
+
def log10(x):
|
18 |
+
numerator = K.log(x)
|
19 |
+
denominator = K.log(K.constant(10, dtype=numerator.dtype))
|
20 |
+
return numerator / denominator
|
21 |
+
|
22 |
+
def bright_psnr(y_true, y_pred):
|
23 |
+
mse = K.mean((K.abs(y_pred[:,:,:,:3] - y_true[:,:,:,:3])) ** 2)
|
24 |
+
max_num = 1.0
|
25 |
+
psnr = 10 * log10(max_num ** 2 / mse)
|
26 |
+
return psnr
|
27 |
+
|
28 |
+
def _tf_fspecial_gauss(size, sigma):
|
29 |
+
"""Function to mimic the 'fspecial' gaussian MATLAB function
|
30 |
+
"""
|
31 |
+
x_data, y_data = np.mgrid[-size//2 + 1:size//2 + 1, -size//2 + 1:size//2 + 1]
|
32 |
+
|
33 |
+
x_data = np.expand_dims(x_data, axis=-1)
|
34 |
+
x_data = np.expand_dims(x_data, axis=-1)
|
35 |
+
|
36 |
+
y_data = np.expand_dims(y_data, axis=-1)
|
37 |
+
y_data = np.expand_dims(y_data, axis=-1)
|
38 |
+
|
39 |
+
x = tf.constant(x_data, dtype=tf.float32)
|
40 |
+
y = tf.constant(y_data, dtype=tf.float32)
|
41 |
+
|
42 |
+
g = tf.exp(-((x**2 + y**2)/(2.0*sigma**2)))
|
43 |
+
return g / tf.reduce_sum(g)
|
44 |
+
|
45 |
+
def tf_ssim(img1, img2, cs_map=False, mean_metric=True, size=11, sigma=1.5):
|
46 |
+
window = _tf_fspecial_gauss(size, sigma) # window shape [size, size]
|
47 |
+
K1 = 0.01
|
48 |
+
K2 = 0.03
|
49 |
+
L = 1 # depth of image (255 in case the image has a differnt scale)
|
50 |
+
C1 = (K1*L)**2
|
51 |
+
C2 = (K2*L)**2
|
52 |
+
mu1 = tf.nn.conv2d(img1, window, strides=[1,1,1,1], padding='VALID')
|
53 |
+
mu2 = tf.nn.conv2d(img2, window, strides=[1,1,1,1],padding='VALID')
|
54 |
+
mu1_sq = mu1*mu1
|
55 |
+
mu2_sq = mu2*mu2
|
56 |
+
mu1_mu2 = mu1*mu2
|
57 |
+
sigma1_sq = tf.nn.conv2d(img1*img1, window, strides=[1,1,1,1],padding='VALID') - mu1_sq
|
58 |
+
sigma2_sq = tf.nn.conv2d(img2*img2, window, strides=[1,1,1,1],padding='VALID') - mu2_sq
|
59 |
+
sigma12 = tf.nn.conv2d(img1*img2, window, strides=[1,1,1,1],padding='VALID') - mu1_mu2
|
60 |
+
if cs_map:
|
61 |
+
value = (((2*mu1_mu2 + C1)*(2*sigma12 + C2))/((mu1_sq + mu2_sq + C1)*
|
62 |
+
(sigma1_sq + sigma2_sq + C2)),
|
63 |
+
(2.0*sigma12 + C2)/(sigma1_sq + sigma2_sq + C2))
|
64 |
+
else:
|
65 |
+
value = ((2*mu1_mu2 + C1)*(2*sigma12 + C2))/((mu1_sq + mu2_sq + C1)*
|
66 |
+
(sigma1_sq + sigma2_sq + C2))
|
67 |
+
|
68 |
+
if mean_metric:
|
69 |
+
value = tf.reduce_mean(value)
|
70 |
+
return value
|
71 |
+
|
72 |
+
def tf_ms_ssim(img1, img2, mean_metric=True, level=5):
|
73 |
+
weight = tf.constant([0.0448, 0.2856, 0.3001, 0.2363, 0.1333], dtype=tf.float32)
|
74 |
+
mssim = []
|
75 |
+
mcs = []
|
76 |
+
for l in range(level):
|
77 |
+
ssim_map, cs_map = tf_ssim(img1, img2, cs_map=True, mean_metric=False)
|
78 |
+
mssim.append(tf.reduce_mean(ssim_map))
|
79 |
+
mcs.append(tf.reduce_mean(cs_map))
|
80 |
+
filtered_im1 = tf.nn.avg_pool(img1, [1,2,2,1], [1,2,2,1], padding='SAME')
|
81 |
+
filtered_im2 = tf.nn.avg_pool(img2, [1,2,2,1], [1,2,2,1], padding='SAME')
|
82 |
+
img1 = filtered_im1
|
83 |
+
img2 = filtered_im2
|
84 |
+
|
85 |
+
# list to tensor of dim D+1
|
86 |
+
mssim = tf.stack(mssim, axis=0)
|
87 |
+
mcs = tf.stack(mcs, axis=0)
|
88 |
+
|
89 |
+
value = (tf.reduce_prod(mcs[0:level-1]**weight[0:level-1])*
|
90 |
+
(mssim[level-1]**weight[level-1]))
|
91 |
+
|
92 |
+
if mean_metric:
|
93 |
+
value = tf.reduce_mean(value)
|
94 |
+
return value
|
95 |
+
|
96 |
+
def bright_SSIM(y_true, y_pred):
|
97 |
+
SSIM_loss = tf_ssim(tf.expand_dims(y_pred[:,:,:,0], -1), tf.expand_dims(y_true[:,:,:,0], -1))+tf_ssim(tf.expand_dims(y_pred[:,:,:,1], -1), tf.expand_dims(y_true[:,:,:,1], -1)) + tf_ssim(tf.expand_dims(y_pred[:,:,:,2], -1), tf.expand_dims(y_true[:,:,:,2], -1))
|
98 |
+
return SSIM_loss/3
|
99 |
+
|
100 |
+
def psnr_cau(y_true, y_pred):
|
101 |
+
mse = np.mean((np.abs(y_pred - y_true)) ** 2)
|
102 |
+
max_num = 1.0
|
103 |
+
psnr = 10 * np.log10(max_num ** 2 / mse)
|
104 |
+
return psnr
|
105 |
+
|
106 |
+
def save_model(model, name, epoch, batch_i):
|
107 |
+
modelname = './Res_models/' + str(epoch) + '_' + str(batch_i) + name + '.h5'
|
108 |
+
model.save_weights(modelname)
|
109 |
+
|
110 |
+
def imread_color(path):
|
111 |
+
img = cv.imread(path, cv.IMREAD_COLOR | cv.IMREAD_ANYDEPTH) / 255.
|
112 |
+
b, g, r = cv.split(img)
|
113 |
+
img_rgb = cv.merge([r, g, b])
|
114 |
+
return img_rgb
|
115 |
+
# return scipy.misc.imread(path, mode='RGB').astype(np.float) / 255.
|
116 |
+
|
117 |
+
def imwrite(path, img):
|
118 |
+
r, g, b = cv.split(img*255)
|
119 |
+
img_rgb = cv.merge([b, g, r])
|
120 |
+
cv.imwrite(path, img_rgb)
|
121 |
+
# scipy.misc.toimage(img * 255, high=255, low=0, cmin=0, cmax=255).save(path)
|
122 |
+
|
123 |
+
def range_scale(x):
|
124 |
+
return x * 2 - 1.
|