Spaces:
Running
Running
import gradio as gr | |
from weight_detector import WeightDetector | |
import tempfile | |
import os | |
from PIL import Image | |
import requests | |
from io import BytesIO | |
# Initialize detector | |
detector = WeightDetector() | |
def process_input(image_source: str, image_upload=None, image_url: str = "") -> dict: | |
"""Process image and return results with IST""" | |
temp_img_path = None | |
try: | |
# Handle different input types | |
if image_source == "upload" and image_upload is not None: | |
img = image_upload | |
elif image_source == "url" and image_url: | |
response = requests.get(image_url) | |
img = Image.open(BytesIO(response.content)) | |
else: | |
return { | |
"weight": None, | |
"message": "No valid image provided", | |
"image": None, | |
"time": detector.get_current_ist() | |
} | |
# Save to temp file for processing | |
with tempfile.NamedTemporaryFile(suffix=".jpg", delete=False) as f: | |
temp_img_path = f.name | |
img.save(f.name) | |
# Detect weight | |
weight, time, annotated_img = detector.detect_weight(temp_img_path) | |
# Format result message | |
if weight is not None: | |
message = f"โ Detected weight: {weight:.2f}g at {time}" | |
else: | |
message = f"โ No weight value detected at {time}" | |
return { | |
"weight": weight, | |
"message": message, | |
"image": annotated_img, | |
"time": time | |
} | |
except Exception as e: | |
return { | |
"weight": None, | |
"message": f"Error: {str(e)}", | |
"image": None, | |
"time": detector.get_current_ist() | |
} | |
finally: | |
if temp_img_path and os.path.exists(temp_img_path): | |
os.unlink(temp_img_path) | |
# Custom CSS for better mobile display | |
css = """ | |
#mobile-view { | |
display: none; | |
} | |
@media screen and (max-width: 768px) { | |
#desktop-view { | |
display: none; | |
} | |
#mobile-view { | |
display: block; | |
} | |
} | |
""" | |
# Gradio interface | |
with gr.Blocks(title="Auto Weight Logger", css=css) as demo: | |
gr.Markdown(""" | |
# ๐๏ธ Auto Weight Logger | |
Capture or upload an image of a digital scale to automatically detect the weight value. | |
""") | |
with gr.Row(): | |
with gr.Column(): | |
image_source = gr.Radio( | |
["upload", "url"], | |
label="Image Source", | |
value="upload", | |
elem_id="source-select" | |
) | |
image_upload = gr.Image( | |
sources=["upload", "webcam"], | |
type="pil", | |
label="Upload Image or Use Webcam", | |
elem_id="image-upload" | |
) | |
image_url = gr.Textbox( | |
label="Image URL", | |
visible=False, | |
elem_id="image-url" | |
) | |
submit_btn = gr.Button("Detect Weight", variant="primary") | |
with gr.Column(): | |
weight_value = gr.Number( | |
label="Detected Weight (grams)", | |
interactive=False, | |
elem_id="weight-value" | |
) | |
detection_time = gr.Textbox( | |
label="Detection Time (IST)", | |
interactive=False, | |
elem_id="detection-time" | |
) | |
result_message = gr.Textbox( | |
label="Result", | |
interactive=False, | |
elem_id="result-message" | |
) | |
annotated_image = gr.Image( | |
label="Annotated Image", | |
interactive=False, | |
elem_id="annotated-image" | |
) | |
# Mobile view toggle | |
with gr.Column(visible=False, elem_id="mobile-view"): | |
gr.Markdown("### Mobile Instructions") | |
gr.Markdown("1. Tap 'Webcam' to capture\n2. Tap 'Detect Weight'") | |
# Show/hide URL input based on selection | |
def toggle_url_visibility(source): | |
return gr.Textbox(visible=source == "url") | |
image_source.change( | |
toggle_url_visibility, | |
inputs=image_source, | |
outputs=image_url | |
) | |
# Process submission | |
submit_btn.click( | |
process_input, | |
inputs=[image_source, image_upload, image_url], | |
outputs={ | |
"weight": weight_value, | |
"message": result_message, | |
"image": annotated_image, | |
"time": detection_time | |
} | |
) | |
# For Hugging Face Spaces | |
demo.launch() |