aslan-ng commited on
Commit
b655d24
·
verified ·
1 Parent(s): 5044969

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +86 -0
app.py ADDED
@@ -0,0 +1,86 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import io, os, tempfile, pathlib, zipfile, shutil
2
+ from PIL import Image, ImageOps
3
+ import pandas as pd # needed to hold predictor output, but we won't return any DataFrame
4
+ from huggingface_hub import hf_hub_download
5
+ import autogluon.multimodal as ag
6
+ import gradio as gr
7
+
8
+ MODEL_REPO_ID = "its-zion-18/sign-image-autogluon-predictor"
9
+ ZIP_FILENAME = "autogluon_image_predictor_dir.zip"
10
+ CACHE_DIR = pathlib.Path("hf_assets")
11
+ EXTRACT_DIR = CACHE_DIR / "predictor_native"
12
+
13
+ CLASS_LABELS = {0: "Other sign", 1: "Stop sign"}
14
+ DEFAULT_SIZE = 224
15
+
16
+ def _prepare_predictor_dir() -> str:
17
+ CACHE_DIR.mkdir(parents=True, exist_ok=True)
18
+ local_zip = hf_hub_download(
19
+ repo_id=MODEL_REPO_ID,
20
+ filename=ZIP_FILENAME,
21
+ repo_type="model",
22
+ local_dir=str(CACHE_DIR),
23
+ local_dir_use_symlinks=False,
24
+ )
25
+ if EXTRACT_DIR.exists():
26
+ shutil.rmtree(EXTRACT_DIR)
27
+ EXTRACT_DIR.mkdir(parents=True, exist_ok=True)
28
+ with zipfile.ZipFile(local_zip, "r") as zf:
29
+ zf.extractall(str(EXTRACT_DIR))
30
+ contents = list(EXTRACT_DIR.iterdir())
31
+ return str(contents[0] if len(contents) == 1 and contents[0].is_dir() else EXTRACT_DIR)
32
+
33
+ PREDICTOR = ag.MultiModalPredictor.load(_prepare_predictor_dir())
34
+
35
+ def preprocess_for_model(img: Image.Image, size: int = DEFAULT_SIZE) -> Image.Image:
36
+ return ImageOps.fit(img, (size, size), method=Image.BICUBIC, centering=(0.5, 0.5))
37
+
38
+ # -------------------------
39
+ # Prediction (return 4 values to match your outputs)
40
+ # -------------------------
41
+ def predict(img: Image.Image):
42
+ if img is None:
43
+ return None, None, {"Error": 1.0}, "**Error:** No image provided."
44
+ pre_img = preprocess_for_model(img, DEFAULT_SIZE)
45
+
46
+ # temp save for AutoGluon
47
+ tmpdir = pathlib.Path(tempfile.mkdtemp())
48
+ img_path = tmpdir / "input.png"
49
+ pre_img.save(img_path)
50
+
51
+ df = pd.DataFrame({"image": [str(img_path)]})
52
+ proba_df = PREDICTOR.predict_proba(df)
53
+ row = proba_df.iloc[0]
54
+
55
+ # Handle int or str column names
56
+ p0 = float(row.get(0, row.get("0", 0.0)))
57
+ p1 = float(row.get(1, row.get("1", 0.0)))
58
+
59
+ pretty = {CLASS_LABELS[0]: p0, CLASS_LABELS[1]: p1}
60
+ status = "" # empty if OK
61
+
62
+ # EXACTLY 4 returns to match your outputs list
63
+ return img, pretty, status
64
+
65
+ EXAMPLES = [
66
+ "https://drive.google.com/uc?id=1OwjdQdiclDOCuUirVsCX-_J1q1Y_G-Xs",
67
+ "https://drive.google.com/uc?id=1g9XwRJGcqYwJ_mFtHj25ZE1w2VZPkBiR",
68
+ "https://drive.google.com/uc?id=1MH5aIvHWKdamwuzdQPWlNwaoRE3c2bVb"
69
+ ]
70
+
71
+ demo = gr.Interface(
72
+ fn=predict,
73
+ inputs=gr.Image(type="pil", label="Input image (PNG/JPG)", sources=["upload", "webcam"]),
74
+ outputs=[
75
+ gr.Image(label="Preprocessed"),
76
+ gr.Label(num_top_classes=2, label="Class probabilities"),
77
+ gr.Markdown(label="Status"),
78
+ ],
79
+ title="🪧 Sign Identification",
80
+ description="Upload a PNG/JPG. Predicts Stop vs Other sign.",
81
+ allow_flagging="never",
82
+ examples=EXAMPLES,
83
+ )
84
+
85
+ if __name__ == "__main__":
86
+ demo.launch()