ysakhale commited on
Commit
98e82a1
·
verified ·
1 Parent(s): 42a1454

Upload folder using huggingface_hub

Browse files
Files changed (3) hide show
  1. README.md +24 -5
  2. app.py +108 -0
  3. requirements.txt +7 -0
README.md CHANGED
@@ -1,12 +1,31 @@
1
  ---
2
  title: Sign Image Classifier
3
- emoji: 🏆
4
- colorFrom: indigo
5
- colorTo: pink
6
  sdk: gradio
7
- sdk_version: 5.47.2
8
  app_file: app.py
9
  pinned: false
10
  ---
11
 
12
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  ---
2
  title: Sign Image Classifier
3
+ emoji: 🖼️
4
+ colorFrom: blue
5
+ colorTo: green
6
  sdk: gradio
7
+ sdk_version: "4.31.5"
8
  app_file: app.py
9
  pinned: false
10
  ---
11
 
12
+ # Sign Image Classifier Classmate Model
13
+
14
+ This Space wraps a classmate-trained AutoGluon `MultiModalPredictor` for **sign identification**.
15
+
16
+ ## Dataset and Model
17
+ - Model: [its-zion-18/sign-image-autogluon-predictor](https://huggingface.co/its-zion-18/sign-image-autogluon-predictor)
18
+ - Dataset: [ecopus/sign_identification](https://huggingface.co/datasets/ecopus/sign_identification)
19
+
20
+ ## How it works
21
+ - Upload an image (PNG/JPG) or use webcam.
22
+ - App shows both the **original** and the **preprocessed** image that goes into the model.
23
+ - Adjustable preprocessing parameters:
24
+ - Resize side
25
+ - Keep aspect ratio
26
+
27
+ ## Output
28
+ - Sorted class probabilities.
29
+
30
+ ## Limitations
31
+ - The model achieved 100% accuracy on the original split, but since the augmented split was derived from the original images (rotations, flips, etc.), there may be data leakage. Generalization performance is uncertain.
app.py ADDED
@@ -0,0 +1,108 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import shutil
3
+ import zipfile
4
+ import pathlib
5
+ import tempfile
6
+ import pandas as pd
7
+ from PIL import Image
8
+ import gradio
9
+ import huggingface_hub
10
+ import autogluon.multimodal as ag_mm
11
+ from datasets import load_dataset
12
+
13
+ MODEL_REPO_ID = "its-zion-18/sign-image-autogluon-predictor"
14
+ ZIP_FILENAME = "autogluon_image_predictor_dir.zip"
15
+ HF_TOKEN = os.environ.get("HUGGINGFACEHUB_API_TOKEN", None)
16
+
17
+ CACHE_DIR = pathlib.Path("hf_assets")
18
+ EXTRACT_DIR = CACHE_DIR / "predictor_native"
19
+
20
+ ALLOWED_EXTS = {".png", ".jpg", ".jpeg"}
21
+ MAX_FILE_MB = 5
22
+
23
+ def _prepare_predictor_dir() -> str:
24
+ CACHE_DIR.mkdir(parents=True, exist_ok=True)
25
+ local_zip = huggingface_hub.hf_hub_download(
26
+ repo_id=MODEL_REPO_ID,
27
+ filename=ZIP_FILENAME,
28
+ repo_type="model",
29
+ token=HF_TOKEN,
30
+ local_dir=str(CACHE_DIR),
31
+ local_dir_use_symlinks=False,
32
+ )
33
+ if EXTRACT_DIR.exists():
34
+ shutil.rmtree(EXTRACT_DIR)
35
+ EXTRACT_DIR.mkdir(parents=True, exist_ok=True)
36
+ with zipfile.ZipFile(local_zip, "r") as zf:
37
+ zf.extractall(str(EXTRACT_DIR))
38
+ contents = list(EXTRACT_DIR.iterdir())
39
+ predictor_root = contents[0] if (len(contents) == 1 and contents[0].is_dir()) else EXTRACT_DIR
40
+ return str(predictor_root)
41
+
42
+ PREDICTOR_DIR = _prepare_predictor_dir()
43
+ PREDICTOR = ag_mm.MultiModalPredictor.load(PREDICTOR_DIR)
44
+
45
+ def _validate_image_file(tmp_path: pathlib.Path) -> None:
46
+ size_mb = tmp_path.stat().st_size / (1024 * 1024)
47
+ if size_mb > MAX_FILE_MB:
48
+ raise ValueError(f"File too large: {size_mb:.2f} MB > {MAX_FILE_MB} MB")
49
+ if tmp_path.suffix.lower() not in ALLOWED_EXTS:
50
+ raise ValueError(f"Unsupported file type: {tmp_path.suffix}. Allowed: {sorted(ALLOWED_EXTS)}")
51
+
52
+ def _preprocess_for_model(pil_img: Image.Image, resize_side: int, keep_aspect: bool) -> Image.Image:
53
+ img = pil_img.convert("RGB")
54
+ if keep_aspect:
55
+ img.thumbnail((resize_side, resize_side), Image.BILINEAR)
56
+ else:
57
+ img = img.resize((resize_side, resize_side), Image.BILINEAR)
58
+ return img
59
+
60
+ def do_predict(pil_img: Image.Image, resize_side: int = 224, keep_aspect: bool = True):
61
+ if pil_img is None:
62
+ return None, None, {"Error": "No image provided."}
63
+
64
+ tmpdir = pathlib.Path(tempfile.mkdtemp())
65
+ orig_path = tmpdir / "original.png"
66
+ pil_img.save(orig_path, format="PNG")
67
+ _validate_image_file(orig_path)
68
+
69
+ pre_img = _preprocess_for_model(pil_img, resize_side=resize_side, keep_aspect=keep_aspect)
70
+ pre_path = tmpdir / "preprocessed.png"
71
+ pre_img.save(pre_path, format="PNG")
72
+
73
+ df = pd.DataFrame({"image": [str(pre_path)]})
74
+ proba_df = PREDICTOR.predict_proba(df)
75
+
76
+ row = proba_df.iloc[0]
77
+ pretty = {str(k): float(v) for k, v in row.items()}
78
+ pretty = dict(sorted(pretty.items(), key=lambda kv: kv[1], reverse=True))
79
+
80
+ return pil_img, pre_img, pretty
81
+
82
+ # Prepare 3 example images from dataset
83
+ ds = load_dataset("ecopus/sign_identification", split="original")
84
+ EXAMPLES = [[ds[i]["image"]] for i in range(3)]
85
+
86
+ with gradio.Blocks() as demo:
87
+ gradio.Markdown("# Sign Image Classifier — Classmate Model")
88
+ gradio.Markdown("Upload an image (PNG/JPG) or use webcam. The app shows both the original and preprocessed (resized) version.")
89
+
90
+ with gradio.Row():
91
+ image_in = gradio.Image(type="pil", label="Upload Image", sources=["upload", "webcam"])
92
+ with gradio.Column():
93
+ resize_side = gradio.Slider(64, 512, value=224, step=16, label="Resize side (pixels)")
94
+ keep_aspect = gradio.Checkbox(value=True, label="Keep aspect ratio")
95
+
96
+ with gradio.Row():
97
+ orig_out = gradio.Image(type="pil", label="Original")
98
+ prep_out = gradio.Image(type="pil", label="Preprocessed")
99
+
100
+ proba_out = gradio.Label(num_top_classes=5, label="Class Probabilities")
101
+
102
+ for comp in [image_in, resize_side, keep_aspect]:
103
+ comp.change(fn=do_predict, inputs=[image_in, resize_side, keep_aspect],
104
+ outputs=[orig_out, prep_out, proba_out])
105
+
106
+ gradio.Examples(examples=EXAMPLES, inputs=[image_in], label="Example Images", cache_examples=False)
107
+
108
+ demo.launch()
requirements.txt ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ gradio
2
+ huggingface_hub
3
+ pandas
4
+ pillow
5
+ torch
6
+ autogluon.multimodal
7
+ datasets