Spaces:
Sleeping
Sleeping
Add zoom sliders for output and preprocessed images
Browse files- Add zoom sliders (50-200%) for both detected and preprocessed images
- Zoom sliders work on all browsers/OS without keyboard shortcuts
- Dynamically resize images based on slider value
- Clear button now resets zoom images as well
- Better UX for detailed inspection of detections
app.py
CHANGED
|
@@ -4,6 +4,7 @@ import numpy as np
|
|
| 4 |
from model import TrafficSignDetector
|
| 5 |
import sys
|
| 6 |
import io
|
|
|
|
| 7 |
|
| 8 |
# Load the detector
|
| 9 |
detector = TrafficSignDetector('config.yaml')
|
|
@@ -35,6 +36,29 @@ def detect_traffic_signs(image, confidence_threshold):
|
|
| 35 |
|
| 36 |
return result_image, preprocessed_image
|
| 37 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 38 |
# Create Gradio interface
|
| 39 |
with gr.Blocks(title="Traffic Sign Detector") as demo:
|
| 40 |
gr.Markdown("# Traffic Sign Detector")
|
|
@@ -42,10 +66,18 @@ with gr.Blocks(title="Traffic Sign Detector") as demo:
|
|
| 42 |
|
| 43 |
with gr.Row():
|
| 44 |
input_image = gr.Image(label="Upload Image", type="pil")
|
| 45 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 46 |
|
| 47 |
with gr.Row():
|
| 48 |
preprocessed_image = gr.Image(label="Preprocessed Image (640x640, Letterboxed)", interactive=False)
|
|
|
|
|
|
|
|
|
|
|
|
|
| 49 |
|
| 50 |
with gr.Row():
|
| 51 |
confidence_threshold = gr.Slider(
|
|
@@ -85,10 +117,24 @@ with gr.Blocks(title="Traffic Sign Detector") as demo:
|
|
| 85 |
queue=True
|
| 86 |
)
|
| 87 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 88 |
# Clear button
|
| 89 |
reset_btn.click(
|
| 90 |
-
fn=lambda: (None, None, None),
|
| 91 |
-
outputs=[input_image, output_image, preprocessed_image]
|
| 92 |
)
|
| 93 |
|
| 94 |
if __name__ == "__main__":
|
|
|
|
| 4 |
from model import TrafficSignDetector
|
| 5 |
import sys
|
| 6 |
import io
|
| 7 |
+
from PIL import Image
|
| 8 |
|
| 9 |
# Load the detector
|
| 10 |
detector = TrafficSignDetector('config.yaml')
|
|
|
|
| 36 |
|
| 37 |
return result_image, preprocessed_image
|
| 38 |
|
| 39 |
+
def zoom_image(image, zoom_level):
|
| 40 |
+
"""
|
| 41 |
+
Zoom image by resizing it.
|
| 42 |
+
:param image: PIL Image
|
| 43 |
+
:param zoom_level: zoom percentage (50-200)
|
| 44 |
+
:return: zoomed image
|
| 45 |
+
"""
|
| 46 |
+
if image is None:
|
| 47 |
+
return None
|
| 48 |
+
|
| 49 |
+
# Convert to PIL if needed
|
| 50 |
+
if isinstance(image, np.ndarray):
|
| 51 |
+
image = Image.fromarray(image)
|
| 52 |
+
|
| 53 |
+
# Calculate new size
|
| 54 |
+
zoom_factor = zoom_level / 100.0
|
| 55 |
+
new_width = int(image.width * zoom_factor)
|
| 56 |
+
new_height = int(image.height * zoom_factor)
|
| 57 |
+
|
| 58 |
+
# Resize image
|
| 59 |
+
zoomed = image.resize((new_width, new_height), Image.Resampling.LANCZOS)
|
| 60 |
+
return zoomed
|
| 61 |
+
|
| 62 |
# Create Gradio interface
|
| 63 |
with gr.Blocks(title="Traffic Sign Detector") as demo:
|
| 64 |
gr.Markdown("# Traffic Sign Detector")
|
|
|
|
| 66 |
|
| 67 |
with gr.Row():
|
| 68 |
input_image = gr.Image(label="Upload Image", type="pil")
|
| 69 |
+
with gr.Column():
|
| 70 |
+
output_image = gr.Image(label="Detected Signs", interactive=False)
|
| 71 |
+
with gr.Row():
|
| 72 |
+
zoom_slider_output = gr.Slider(minimum=50, maximum=200, value=100, step=10, label="Zoom Output (%)")
|
| 73 |
+
output_image_zoomed = gr.Image(label="Zoomed Output", interactive=False, visible=False)
|
| 74 |
|
| 75 |
with gr.Row():
|
| 76 |
preprocessed_image = gr.Image(label="Preprocessed Image (640x640, Letterboxed)", interactive=False)
|
| 77 |
+
with gr.Column():
|
| 78 |
+
gr.Markdown("#### Zoom Preprocessed (%)")
|
| 79 |
+
zoom_slider_preprocessed = gr.Slider(minimum=50, maximum=200, value=100, step=10, label="Zoom Preprocessed")
|
| 80 |
+
preprocessed_image_zoomed = gr.Image(label="Zoomed Preprocessed", interactive=False, visible=False)
|
| 81 |
|
| 82 |
with gr.Row():
|
| 83 |
confidence_threshold = gr.Slider(
|
|
|
|
| 117 |
queue=True
|
| 118 |
)
|
| 119 |
|
| 120 |
+
# Zoom output image
|
| 121 |
+
zoom_slider_output.change(
|
| 122 |
+
fn=zoom_image,
|
| 123 |
+
inputs=[output_image, zoom_slider_output],
|
| 124 |
+
outputs=[output_image_zoomed]
|
| 125 |
+
)
|
| 126 |
+
|
| 127 |
+
# Zoom preprocessed image
|
| 128 |
+
zoom_slider_preprocessed.change(
|
| 129 |
+
fn=zoom_image,
|
| 130 |
+
inputs=[preprocessed_image, zoom_slider_preprocessed],
|
| 131 |
+
outputs=[preprocessed_image_zoomed]
|
| 132 |
+
)
|
| 133 |
+
|
| 134 |
# Clear button
|
| 135 |
reset_btn.click(
|
| 136 |
+
fn=lambda: (None, None, None, None, None),
|
| 137 |
+
outputs=[input_image, output_image, preprocessed_image, output_image_zoomed, preprocessed_image_zoomed]
|
| 138 |
)
|
| 139 |
|
| 140 |
if __name__ == "__main__":
|