Spaces:
Sleeping
Sleeping
Upload 3 files
Browse files- README.md +43 -0
- app.py +69 -0
- requirements.txt +5 -0
README.md
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
title: Stop Sign Predictor
|
| 3 |
+
emoji: 🦀
|
| 4 |
+
colorFrom: yellow
|
| 5 |
+
colorTo: yellow
|
| 6 |
+
sdk: gradio
|
| 7 |
+
sdk_version: 5.47.2
|
| 8 |
+
app_file: app.py
|
| 9 |
+
pinned: false
|
| 10 |
+
license: mit
|
| 11 |
+
---
|
| 12 |
+
# Stop Sign Classifier
|
| 13 |
+
|
| 14 |
+
This is a simple Gradio app that wraps an **AutoGluon MultiModalPredictor** trained on images of stop signs.
|
| 15 |
+
Upload a traffic sign and the model will predict whether it contains a **Stop Sign**.
|
| 16 |
+
|
| 17 |
+
## Features
|
| 18 |
+
- Upload your own image (PNG/JPG) or use your webcam.
|
| 19 |
+
- Get predictions with **probabilities** (Stop Sign vs No Stop Sign).
|
| 20 |
+
- Preview **example images** for quick testing.
|
| 21 |
+
- Built with [AutoGluon](https://auto.gluon.ai/stable/index.html) + [Gradio](https://gradio.app/).
|
| 22 |
+
|
| 23 |
+
## How It Works
|
| 24 |
+
- The trained model is downloaded directly from Hugging Face Hub (`scottymcgee/image-classifier`).
|
| 25 |
+
- Images are preprocessed (resized to 256x256) and passed into the model.
|
| 26 |
+
- Probabilities are returned and displayed in a simple UI.
|
| 27 |
+
|
| 28 |
+
## Example Inputs
|
| 29 |
+
- Clear stop sign picture
|
| 30 |
+
- Street scene without stop sign
|
| 31 |
+
- Mixed images
|
| 32 |
+
|
| 33 |
+
## Files in this Space
|
| 34 |
+
- `app.py`: Gradio interface.
|
| 35 |
+
- `requirements.txt`: Dependencies.
|
| 36 |
+
- `README.md`: This documentation.
|
| 37 |
+
|
| 38 |
+
## Notes
|
| 39 |
+
- This app is for **educational/demo** purposes.
|
| 40 |
+
- Model was trained by a classmate as part of Homework 2 (CMU 24679).
|
| 41 |
+
- Deployment exercise for **Driving an Image Network Model with Gradio** assignment.
|
| 42 |
+
|
| 43 |
+
Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
|
app.py
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import gradio
|
| 2 |
+
import pandas as pd
|
| 3 |
+
import PIL.Image
|
| 4 |
+
import tempfile, pathlib, requests, io
|
| 5 |
+
|
| 6 |
+
from huggingface_hub import snapshot_download
|
| 7 |
+
from autogluon.multimodal import MultiModalPredictor
|
| 8 |
+
|
| 9 |
+
# Hugging Face model repo (no .zip file here, it’s a direct directory)
|
| 10 |
+
MODEL_REPO_ID = "scottymcgee/image-classifier"
|
| 11 |
+
|
| 12 |
+
# Download full repo snapshot locally
|
| 13 |
+
repo_dir = snapshot_download(repo_id=MODEL_REPO_ID)
|
| 14 |
+
|
| 15 |
+
# Load predictor directly
|
| 16 |
+
PREDICTOR = MultiModalPredictor.load(repo_dir)
|
| 17 |
+
|
| 18 |
+
# Explicit class labels
|
| 19 |
+
CLASS_LABELS = {0: "🚫 No Stop Sign", 1: "🛑 Stop Sign"}
|
| 20 |
+
|
| 21 |
+
def do_predict(pil_img: PIL.Image.Image):
|
| 22 |
+
if pil_img is None:
|
| 23 |
+
return {"Error": 1.0}
|
| 24 |
+
pil_resized = pil_img.convert("RGB").resize((256, 256))
|
| 25 |
+
|
| 26 |
+
# Save to tmp for AutoGluon input
|
| 27 |
+
tmpdir = pathlib.Path(tempfile.mkdtemp())
|
| 28 |
+
img_path = tmpdir / "input.png"
|
| 29 |
+
pil_img.save(img_path)
|
| 30 |
+
|
| 31 |
+
df = pd.DataFrame({"image": [str(img_path)]})
|
| 32 |
+
|
| 33 |
+
# Predict probabilities
|
| 34 |
+
proba_df = PREDICTOR.predict_proba(df)
|
| 35 |
+
|
| 36 |
+
# Map columns to nice names
|
| 37 |
+
pretty_dict = {}
|
| 38 |
+
for idx, col in enumerate(proba_df.columns):
|
| 39 |
+
label = CLASS_LABELS.get(idx, str(col))
|
| 40 |
+
pretty_dict[label] = float(proba_df.iloc[0][col])
|
| 41 |
+
return pil_img, pil_resized, pretty_dict
|
| 42 |
+
|
| 43 |
+
EXAMPLES = [
|
| 44 |
+
["examples/stop1.jpg"],
|
| 45 |
+
["examples/no_stop1.jpg"],
|
| 46 |
+
["examples/stop2.jpg"],
|
| 47 |
+
]
|
| 48 |
+
|
| 49 |
+
with gradio.Blocks() as demo:
|
| 50 |
+
gradio.Markdown("# 🛑 Stop Sign Classifier")
|
| 51 |
+
gradio.Markdown("Upload a traffic image. The model shows the **original**, the **preprocessed**, and the prediction.")
|
| 52 |
+
|
| 53 |
+
with gradio.Row():
|
| 54 |
+
image_in = gradio.Image(type="pil", label="Upload image", sources=["upload", "webcam"])
|
| 55 |
+
proc_out = gradio.Image(type="pil", label="Preprocessed (256x256)")
|
| 56 |
+
proba_pretty = gradio.Label(num_top_classes=2, label="Class probabilities")
|
| 57 |
+
|
| 58 |
+
image_in.change(fn=do_predict, inputs=[image_in], outputs=[orig_out, proc_out, proba_pretty])
|
| 59 |
+
|
| 60 |
+
gradio.Examples(
|
| 61 |
+
examples=EXAMPLES,
|
| 62 |
+
inputs=[image_in],
|
| 63 |
+
outputs=[proc_out, proba_pretty],
|
| 64 |
+
fn=do_predict,
|
| 65 |
+
cache_examples=False,
|
| 66 |
+
)
|
| 67 |
+
|
| 68 |
+
if __name__ == "__main__":
|
| 69 |
+
demo.launch()
|
requirements.txt
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
autogluon.multimodal
|
| 2 |
+
gradio
|
| 3 |
+
huggingface_hub
|
| 4 |
+
pillow
|
| 5 |
+
pandas
|