Spaces:
Sleeping
Sleeping
Add full logging and preprocessed image visualization
Browse files
app.py
CHANGED
|
@@ -2,6 +2,8 @@ import gradio as gr
|
|
| 2 |
import cv2
|
| 3 |
import numpy as np
|
| 4 |
from model import TrafficSignDetector
|
|
|
|
|
|
|
| 5 |
|
| 6 |
# Load the detector
|
| 7 |
detector = TrafficSignDetector('config.yaml')
|
|
@@ -10,8 +12,9 @@ def detect_traffic_signs(image):
|
|
| 10 |
"""
|
| 11 |
Process the uploaded image and return the image with detected signs.
|
| 12 |
:param image: PIL Image or numpy array
|
| 13 |
-
:return:
|
| 14 |
"""
|
|
|
|
| 15 |
print(f"Received image type: {type(image)}")
|
| 16 |
# Convert PIL to numpy if necessary
|
| 17 |
if hasattr(image, 'convert'):
|
|
@@ -22,13 +25,14 @@ def detect_traffic_signs(image):
|
|
| 22 |
image = cv2.cvtColor(image, cv2.COLOR_RGB2BGR)
|
| 23 |
print(f"Converted to BGR, shape: {image.shape}")
|
| 24 |
|
| 25 |
-
# Perform detection
|
| 26 |
-
result_image = detector.detect(image)
|
| 27 |
|
| 28 |
# Convert back to RGB for Gradio
|
| 29 |
result_image = cv2.cvtColor(result_image, cv2.COLOR_BGR2RGB)
|
|
|
|
| 30 |
|
| 31 |
-
return result_image
|
| 32 |
|
| 33 |
# Create Gradio interface
|
| 34 |
with gr.Blocks(title="Traffic Sign Detector") as demo:
|
|
@@ -39,8 +43,16 @@ with gr.Blocks(title="Traffic Sign Detector") as demo:
|
|
| 39 |
input_image = gr.Image(label="Upload Image", type="pil")
|
| 40 |
output_image = gr.Image(label="Detected Signs")
|
| 41 |
|
|
|
|
|
|
|
|
|
|
| 42 |
detect_btn = gr.Button("Detect Traffic Signs")
|
| 43 |
-
detect_btn.click(
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 44 |
|
| 45 |
if __name__ == "__main__":
|
| 46 |
-
demo.launch(server_name="0.0.0.0", server_port=7860)
|
|
|
|
| 2 |
import cv2
|
| 3 |
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')
|
|
|
|
| 12 |
"""
|
| 13 |
Process the uploaded image and return the image with detected signs.
|
| 14 |
:param image: PIL Image or numpy array
|
| 15 |
+
:return: tuple of (detected image, preprocessed image)
|
| 16 |
"""
|
| 17 |
+
# Redirect stdout to capture all logs
|
| 18 |
print(f"Received image type: {type(image)}")
|
| 19 |
# Convert PIL to numpy if necessary
|
| 20 |
if hasattr(image, 'convert'):
|
|
|
|
| 25 |
image = cv2.cvtColor(image, cv2.COLOR_RGB2BGR)
|
| 26 |
print(f"Converted to BGR, shape: {image.shape}")
|
| 27 |
|
| 28 |
+
# Perform detection (returns tuple of (detected_image, preprocessed_image))
|
| 29 |
+
result_image, preprocessed_image = detector.detect(image)
|
| 30 |
|
| 31 |
# Convert back to RGB for Gradio
|
| 32 |
result_image = cv2.cvtColor(result_image, cv2.COLOR_BGR2RGB)
|
| 33 |
+
preprocessed_image = cv2.cvtColor(preprocessed_image, cv2.COLOR_BGR2RGB)
|
| 34 |
|
| 35 |
+
return result_image, preprocessed_image
|
| 36 |
|
| 37 |
# Create Gradio interface
|
| 38 |
with gr.Blocks(title="Traffic Sign Detector") as demo:
|
|
|
|
| 43 |
input_image = gr.Image(label="Upload Image", type="pil")
|
| 44 |
output_image = gr.Image(label="Detected Signs")
|
| 45 |
|
| 46 |
+
with gr.Row():
|
| 47 |
+
preprocessed_image = gr.Image(label="Preprocessed Image (640x640, Letterboxed)")
|
| 48 |
+
|
| 49 |
detect_btn = gr.Button("Detect Traffic Signs")
|
| 50 |
+
detect_btn.click(
|
| 51 |
+
fn=detect_traffic_signs,
|
| 52 |
+
inputs=input_image,
|
| 53 |
+
outputs=[output_image, preprocessed_image],
|
| 54 |
+
queue=True # Enable queue to ensure logs are shown
|
| 55 |
+
)
|
| 56 |
|
| 57 |
if __name__ == "__main__":
|
| 58 |
+
demo.queue().launch(server_name="0.0.0.0", server_port=7860)
|
model.py
CHANGED
|
@@ -151,9 +151,10 @@ class TrafficSignDetector:
|
|
| 151 |
"""
|
| 152 |
Perform inference on the image and draw bounding boxes.
|
| 153 |
:param image: numpy array of the image
|
| 154 |
-
:return: image with drawn bounding boxes
|
| 155 |
"""
|
| 156 |
-
print(f"
|
|
|
|
| 157 |
|
| 158 |
# Store original image for drawing (uint8)
|
| 159 |
original_image = image.copy()
|
|
@@ -165,6 +166,9 @@ class TrafficSignDetector:
|
|
| 165 |
# Normalize pixel values for inference
|
| 166 |
image = self._preprocess(image)
|
| 167 |
|
|
|
|
|
|
|
|
|
|
| 168 |
# Use imgsz=640 to match training size
|
| 169 |
# Use iou_threshold for NMS (Non-Maximum Suppression) to remove overlapping boxes
|
| 170 |
results = self.model(image, conf=self.conf_threshold, imgsz=640, iou=0.45)
|
|
@@ -207,4 +211,5 @@ class TrafficSignDetector:
|
|
| 207 |
label = f"{self.classes[cls]}: {conf:.2f}"
|
| 208 |
cv2.putText(original_image, label, (x1, y1 - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, self.text_color, 2)
|
| 209 |
|
| 210 |
-
|
|
|
|
|
|
| 151 |
"""
|
| 152 |
Perform inference on the image and draw bounding boxes.
|
| 153 |
:param image: numpy array of the image
|
| 154 |
+
:return: tuple of (image with drawn bounding boxes, preprocessed image for visualization)
|
| 155 |
"""
|
| 156 |
+
print(f"\n{'='*80}")
|
| 157 |
+
print(f"INPUT IMAGE shape: {image.shape}")
|
| 158 |
|
| 159 |
# Store original image for drawing (uint8)
|
| 160 |
original_image = image.copy()
|
|
|
|
| 166 |
# Normalize pixel values for inference
|
| 167 |
image = self._preprocess(image)
|
| 168 |
|
| 169 |
+
# Store preprocessed image for visualization (convert back to 0-255 for display)
|
| 170 |
+
preprocessed_display = (image * 255).astype(np.uint8) if image.max() <= 1.0 else image.copy()
|
| 171 |
+
|
| 172 |
# Use imgsz=640 to match training size
|
| 173 |
# Use iou_threshold for NMS (Non-Maximum Suppression) to remove overlapping boxes
|
| 174 |
results = self.model(image, conf=self.conf_threshold, imgsz=640, iou=0.45)
|
|
|
|
| 211 |
label = f"{self.classes[cls]}: {conf:.2f}"
|
| 212 |
cv2.putText(original_image, label, (x1, y1 - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, self.text_color, 2)
|
| 213 |
|
| 214 |
+
print("="*80 + "\n")
|
| 215 |
+
return original_image, preprocessed_display
|