Spaces:
Sleeping
Sleeping
Update saliency_gradio.py
Browse files- saliency_gradio.py +54 -62
saliency_gradio.py
CHANGED
@@ -1,111 +1,103 @@
|
|
1 |
-
import
|
|
|
2 |
import numpy as np
|
|
|
3 |
import tensorflow as tf
|
4 |
-
from huggingface_hub import
|
5 |
-
import gradio as gr
|
6 |
|
7 |
-
# Load
|
8 |
model = from_pretrained_keras("alexanderkroner/MSI-Net")
|
9 |
hf_dir = snapshot_download(repo_id="alexanderkroner/MSI-Net")
|
10 |
|
11 |
def get_target_shape(original_shape):
|
12 |
-
|
13 |
-
|
14 |
-
landscape_mode = abs(original_aspect_ratio - 240 / 320)
|
15 |
-
portrait_mode = abs(original_aspect_ratio - 320 / 240)
|
16 |
-
best_mode = min(square_mode, landscape_mode, portrait_mode)
|
17 |
-
if best_mode == square_mode:
|
18 |
return (320, 320)
|
19 |
-
elif
|
20 |
return (240, 320)
|
21 |
-
|
22 |
-
return (320, 240)
|
23 |
|
24 |
def preprocess_input(input_image, target_shape):
|
25 |
input_tensor = tf.expand_dims(input_image, axis=0)
|
26 |
input_tensor = tf.image.resize(input_tensor, target_shape, preserve_aspect_ratio=True)
|
27 |
vertical_padding = target_shape[0] - input_tensor.shape[1]
|
28 |
horizontal_padding = target_shape[1] - input_tensor.shape[2]
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
-
|
33 |
-
input_tensor = tf.pad(
|
34 |
-
input_tensor,
|
35 |
-
[
|
36 |
-
[0, 0],
|
37 |
-
[vertical_padding_1, vertical_padding_2],
|
38 |
-
[horizontal_padding_1, horizontal_padding_2],
|
39 |
-
[0, 0],
|
40 |
-
],
|
41 |
-
)
|
42 |
-
return input_tensor, [vertical_padding_1, vertical_padding_2], [horizontal_padding_1, horizontal_padding_2]
|
43 |
|
44 |
-
def postprocess_output(output_tensor,
|
45 |
output_tensor = output_tensor[
|
46 |
-
:,
|
47 |
-
|
48 |
-
horizontal_padding[0] : output_tensor.shape[2] - horizontal_padding[1],
|
49 |
-
:,
|
50 |
]
|
51 |
output_tensor = tf.image.resize(output_tensor, original_shape)
|
52 |
return output_tensor.numpy().squeeze()
|
53 |
|
54 |
-
def
|
55 |
-
input_image_np = np.array(
|
56 |
original_shape = input_image_np.shape[:2]
|
57 |
target_shape = get_target_shape(original_shape)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
58 |
|
59 |
-
|
|
|
|
|
|
|
|
|
60 |
output_tensor = model(input_tensor)["output"]
|
61 |
-
saliency_gray = postprocess_output(output_tensor,
|
62 |
|
63 |
-
# Total saliency
|
64 |
total_saliency = np.sum(saliency_gray)
|
65 |
-
|
66 |
-
|
67 |
-
|
68 |
-
|
69 |
-
saliency_crop = saliency_gray[y_min:y_max, x_min:x_max]
|
70 |
bbox_sum = np.sum(saliency_crop)
|
71 |
-
bbox_ratio = bbox_sum / total_saliency if total_saliency > 0 else 0.0
|
72 |
-
else:
|
73 |
-
bbox_sum = 0
|
74 |
-
bbox_ratio = 0.0
|
75 |
|
76 |
-
|
77 |
saliency_rgb = plt.cm.inferno(saliency_gray)[..., :3]
|
78 |
alpha = 0.9
|
79 |
-
|
80 |
|
81 |
-
summary =
|
82 |
-
|
83 |
-
|
|
|
|
|
84 |
|
85 |
-
|
86 |
-
return process_image(image)
|
87 |
|
88 |
def predict_dual(image1, image2):
|
89 |
result1_img, result1_val = process_image(image1)
|
90 |
result2_img, result2_val = process_image(image2)
|
91 |
return result1_img, result1_val, result2_img, result2_val
|
92 |
|
|
|
93 |
with gr.Blocks(title="MSI-Net Saliency App") as demo:
|
94 |
gr.Markdown("## MSI-Net Saliency Map Viewer")
|
|
|
95 |
with gr.Tabs():
|
96 |
with gr.Tab("Single Image"):
|
97 |
gr.Markdown("### Upload an image and draw a bounding box to measure saliency inside it.")
|
98 |
with gr.Row():
|
99 |
-
|
|
|
100 |
with gr.Row():
|
101 |
-
|
102 |
-
|
103 |
-
|
104 |
-
|
105 |
-
|
106 |
-
|
107 |
-
outputs=[output_image_single, output_text_single],
|
108 |
-
)
|
109 |
with gr.Tab("Compare Two Images"):
|
110 |
gr.Markdown("### Upload two images to compare their saliency maps and grayscale saliency values.")
|
111 |
with gr.Row():
|
|
|
1 |
+
import gradio as gr
|
2 |
+
from gradio_image_annotation import ImageAnnotation
|
3 |
import numpy as np
|
4 |
+
import matplotlib.pyplot as plt
|
5 |
import tensorflow as tf
|
6 |
+
from huggingface_hub import from_pretrained_keras, snapshot_download
|
|
|
7 |
|
8 |
+
# Load model
|
9 |
model = from_pretrained_keras("alexanderkroner/MSI-Net")
|
10 |
hf_dir = snapshot_download(repo_id="alexanderkroner/MSI-Net")
|
11 |
|
12 |
def get_target_shape(original_shape):
|
13 |
+
aspect = original_shape[0] / original_shape[1]
|
14 |
+
if abs(aspect - 1.0) < min(abs(aspect - 240/320), abs(aspect - 320/240)):
|
|
|
|
|
|
|
|
|
15 |
return (320, 320)
|
16 |
+
elif abs(aspect - 240/320) < abs(aspect - 320/240):
|
17 |
return (240, 320)
|
18 |
+
return (320, 240)
|
|
|
19 |
|
20 |
def preprocess_input(input_image, target_shape):
|
21 |
input_tensor = tf.expand_dims(input_image, axis=0)
|
22 |
input_tensor = tf.image.resize(input_tensor, target_shape, preserve_aspect_ratio=True)
|
23 |
vertical_padding = target_shape[0] - input_tensor.shape[1]
|
24 |
horizontal_padding = target_shape[1] - input_tensor.shape[2]
|
25 |
+
vpad1, vpad2 = vertical_padding // 2, vertical_padding - vertical_padding // 2
|
26 |
+
hpad1, hpad2 = horizontal_padding // 2, horizontal_padding - horizontal_padding // 2
|
27 |
+
input_tensor = tf.pad(input_tensor, [[0,0], [vpad1, vpad2], [hpad1, hpad2], [0,0]])
|
28 |
+
return input_tensor, [vpad1, vpad2], [hpad1, hpad2]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
29 |
|
30 |
+
def postprocess_output(output_tensor, vpad, hpad, original_shape):
|
31 |
output_tensor = output_tensor[
|
32 |
+
:, vpad[0]:output_tensor.shape[1]-vpad[1],
|
33 |
+
hpad[0]:output_tensor.shape[2]-hpad[1], :
|
|
|
|
|
34 |
]
|
35 |
output_tensor = tf.image.resize(output_tensor, original_shape)
|
36 |
return output_tensor.numpy().squeeze()
|
37 |
|
38 |
+
def process_image(image):
|
39 |
+
input_image_np = np.array(image, dtype=np.float32)
|
40 |
original_shape = input_image_np.shape[:2]
|
41 |
target_shape = get_target_shape(original_shape)
|
42 |
+
input_tensor, vpad, hpad = preprocess_input(input_image_np, target_shape)
|
43 |
+
output_tensor = model(input_tensor)["output"]
|
44 |
+
saliency_gray = postprocess_output(output_tensor, vpad, hpad, original_shape)
|
45 |
+
total_saliency = np.sum(saliency_gray)
|
46 |
+
saliency_rgb = plt.cm.inferno(saliency_gray)[..., :3]
|
47 |
+
alpha = 0.9
|
48 |
+
blended = alpha * saliency_rgb + (1 - alpha) * input_image_np / 255
|
49 |
+
return blended, f"Total grayscale saliency: {total_saliency:.2f}"
|
50 |
|
51 |
+
def process_image_with_bbox(image, annotations):
|
52 |
+
input_image_np = np.array(image, dtype=np.float32)
|
53 |
+
original_shape = input_image_np.shape[:2]
|
54 |
+
target_shape = get_target_shape(original_shape)
|
55 |
+
input_tensor, vpad, hpad = preprocess_input(input_image_np, target_shape)
|
56 |
output_tensor = model(input_tensor)["output"]
|
57 |
+
saliency_gray = postprocess_output(output_tensor, vpad, hpad, original_shape)
|
58 |
|
|
|
59 |
total_saliency = np.sum(saliency_gray)
|
60 |
+
bbox_sum = 0.0
|
61 |
+
if annotations and isinstance(annotations, list) and "coordinates" in annotations[0]:
|
62 |
+
x, y, w, h = map(int, annotations[0]["coordinates"])
|
63 |
+
saliency_crop = saliency_gray[y:y+h, x:x+w]
|
|
|
64 |
bbox_sum = np.sum(saliency_crop)
|
|
|
|
|
|
|
|
|
65 |
|
66 |
+
ratio = bbox_sum / total_saliency if total_saliency > 0 else 0
|
67 |
saliency_rgb = plt.cm.inferno(saliency_gray)[..., :3]
|
68 |
alpha = 0.9
|
69 |
+
blended = alpha * saliency_rgb + (1 - alpha) * input_image_np / 255
|
70 |
|
71 |
+
summary = (
|
72 |
+
f"Total saliency: {total_saliency:.2f}\n"
|
73 |
+
f"Bounding box saliency: {bbox_sum:.2f}\n"
|
74 |
+
f"Ratio: {ratio:.4f}"
|
75 |
+
)
|
76 |
|
77 |
+
return blended, summary
|
|
|
78 |
|
79 |
def predict_dual(image1, image2):
|
80 |
result1_img, result1_val = process_image(image1)
|
81 |
result2_img, result2_val = process_image(image2)
|
82 |
return result1_img, result1_val, result2_img, result2_val
|
83 |
|
84 |
+
# Interface
|
85 |
with gr.Blocks(title="MSI-Net Saliency App") as demo:
|
86 |
gr.Markdown("## MSI-Net Saliency Map Viewer")
|
87 |
+
|
88 |
with gr.Tabs():
|
89 |
with gr.Tab("Single Image"):
|
90 |
gr.Markdown("### Upload an image and draw a bounding box to measure saliency inside it.")
|
91 |
with gr.Row():
|
92 |
+
image_input = gr.Image(type="pil", label="Upload Image")
|
93 |
+
annotator = ImageAnnotation()
|
94 |
with gr.Row():
|
95 |
+
image_output = gr.Image(type="numpy", label="Saliency Map")
|
96 |
+
stats_output = gr.Textbox(label="Saliency Stats")
|
97 |
+
button = gr.Button("Generate Saliency")
|
98 |
+
button.click(fn=process_image_with_bbox, inputs=[image_input, annotator], outputs=[image_output, stats_output])
|
99 |
+
image_input.change(fn=lambda img: img, inputs=image_input, outputs=annotator)
|
100 |
+
|
|
|
|
|
101 |
with gr.Tab("Compare Two Images"):
|
102 |
gr.Markdown("### Upload two images to compare their saliency maps and grayscale saliency values.")
|
103 |
with gr.Row():
|