MateuszLis commited on
Commit
9d25848
·
verified ·
1 Parent(s): 356875c

Update saliency_gradio.py

Browse files
Files changed (1) hide show
  1. saliency_gradio.py +54 -62
saliency_gradio.py CHANGED
@@ -1,111 +1,103 @@
1
- import matplotlib.pyplot as plt
 
2
  import numpy as np
 
3
  import tensorflow as tf
4
- from huggingface_hub import snapshot_download, from_pretrained_keras
5
- import gradio as gr
6
 
7
- # Load the model
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
- original_aspect_ratio = original_shape[0] / original_shape[1]
13
- square_mode = abs(original_aspect_ratio - 1.0)
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 best_mode == landscape_mode:
20
  return (240, 320)
21
- else:
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
- vertical_padding_1 = vertical_padding // 2
30
- vertical_padding_2 = vertical_padding - vertical_padding_1
31
- horizontal_padding_1 = horizontal_padding // 2
32
- horizontal_padding_2 = horizontal_padding - horizontal_padding_1
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, vertical_padding, horizontal_padding, original_shape):
45
  output_tensor = output_tensor[
46
- :,
47
- vertical_padding[0] : output_tensor.shape[1] - vertical_padding[1],
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 process_image_with_bbox(input_image, bbox, threshold=0.0):
55
- input_image_np = np.array(input_image, dtype=np.float32)
56
  original_shape = input_image_np.shape[:2]
57
  target_shape = get_target_shape(original_shape)
 
 
 
 
 
 
 
 
58
 
59
- input_tensor, vertical_padding, horizontal_padding = preprocess_input(input_image_np, target_shape)
 
 
 
 
60
  output_tensor = model(input_tensor)["output"]
61
- saliency_gray = postprocess_output(output_tensor, vertical_padding, horizontal_padding, original_shape)
62
 
63
- # Total saliency
64
  total_saliency = np.sum(saliency_gray)
65
-
66
- # Bounding box: bbox = [x_min, y_min, x_max, y_max] in image pixel coordinates
67
- if bbox is not None:
68
- x_min, y_min, x_max, y_max = map(int, bbox)
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
- # Heatmap overlay
77
  saliency_rgb = plt.cm.inferno(saliency_gray)[..., :3]
78
  alpha = 0.9
79
- blended_image = alpha * saliency_rgb + (1 - alpha) * input_image_np / 255
80
 
81
- summary = f"{bbox_ratio:.4f}"
82
-
83
- return blended_image, summary
 
 
84
 
85
- def predict_single(image):
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
- input_image_single = gr.Image(type="pil", tool="select", label="Input Image with Bounding Box")
 
100
  with gr.Row():
101
- output_image_single = gr.Image(type="numpy", label="Saliency Map")
102
- output_text_single = gr.Textbox(label="Saliency Stats")
103
- submit_single = gr.Button("Generate Saliency")
104
- submit_single.click(
105
- fn=process_image_with_bbox,
106
- inputs=[input_image_single, input_image_single.select_region],
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():