Anyuhhh commited on
Commit
fd94015
·
verified ·
1 Parent(s): 20db8ec

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +176 -0
app.py ADDED
@@ -0,0 +1,176 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import shutil
3
+ import zipfile
4
+ import pathlib
5
+ import tempfile
6
+ import gradio
7
+ import pandas
8
+ import PIL.Image
9
+ import huggingface_hub
10
+ import autogluon.multimodal
11
+
12
+ # Model configuration
13
+ MODEL_REPO_ID = "Anyuhhh/sign-language-recognition" # Your Hugging Face Space repo
14
+ ZIP_FILENAME = "autogluon_image_predictor_dir.zip"
15
+ HF_TOKEN = os.getenv("HF_TOKEN", None) # Optional: only if your repo is private
16
+
17
+ CACHE_DIR = pathlib.Path("hf_assets")
18
+ EXTRACT_DIR = CACHE_DIR / "predictor_native"
19
+
20
+ def _prepare_predictor_dir() -> str:
21
+ """Download and extract the predictor from Hugging Face"""
22
+ CACHE_DIR.mkdir(parents=True, exist_ok=True)
23
+
24
+ print(f"Downloading model from HuggingFace: {MODEL_REPO_ID}/{ZIP_FILENAME}")
25
+
26
+ try:
27
+ # Download from Hugging Face
28
+ local_zip = huggingface_hub.hf_hub_download(
29
+ repo_id=MODEL_REPO_ID,
30
+ filename=ZIP_FILENAME,
31
+ repo_type="space", # Changed to "space" since you're uploading to your Space repo
32
+ token=HF_TOKEN,
33
+ local_dir=str(CACHE_DIR),
34
+ local_dir_use_symlinks=False,
35
+ )
36
+ print(f"Downloaded to: {local_zip}")
37
+ except Exception as e:
38
+ print(f"Error downloading from Space repo: {e}")
39
+ print("Trying as model repo instead...")
40
+ # Fallback: try as model repo
41
+ local_zip = huggingface_hub.hf_hub_download(
42
+ repo_id=MODEL_REPO_ID,
43
+ filename=ZIP_FILENAME,
44
+ repo_type="model",
45
+ token=HF_TOKEN,
46
+ local_dir=str(CACHE_DIR),
47
+ local_dir_use_symlinks=False,
48
+ )
49
+
50
+ # Clean and recreate extraction directory
51
+ if EXTRACT_DIR.exists():
52
+ shutil.rmtree(EXTRACT_DIR)
53
+ EXTRACT_DIR.mkdir(parents=True, exist_ok=True)
54
+
55
+ # Extract the ZIP file
56
+ print(f"Extracting to: {EXTRACT_DIR}")
57
+ with zipfile.ZipFile(local_zip, "r") as zf:
58
+ zf.extractall(str(EXTRACT_DIR))
59
+
60
+ # Find the predictor directory
61
+ contents = list(EXTRACT_DIR.iterdir())
62
+ predictor_root = contents[0] if (len(contents) == 1 and contents[0].is_dir()) else EXTRACT_DIR
63
+
64
+ print(f"Predictor directory: {predictor_root}")
65
+ return str(predictor_root)
66
+
67
+ # Initialize predictor
68
+ print("Initializing predictor...")
69
+ PREDICTOR_DIR = _prepare_predictor_dir()
70
+ PREDICTOR = autogluon.multimodal.MultiModalPredictor.load(PREDICTOR_DIR)
71
+ print("Predictor loaded successfully!")
72
+
73
+ # Sign language classes A-Z (26 classes)
74
+ CLASS_LABELS = {i: chr(65+i) for i in range(26)} # 0='A', 1='B', ..., 25='Z'
75
+
76
+ def _human_label(c):
77
+ """Convert class index to human-readable label"""
78
+ try:
79
+ ci = int(c)
80
+ return CLASS_LABELS.get(ci, str(c))
81
+ except Exception:
82
+ return CLASS_LABELS.get(c, str(c))
83
+
84
+ def do_predict(pil_img: PIL.Image.Image):
85
+ """Predict sign language letter from image"""
86
+ if pil_img is None:
87
+ return {}, None
88
+
89
+ tmpdir = pathlib.Path(tempfile.mkdtemp())
90
+ img_path = tmpdir / "input.png"
91
+
92
+ # Preprocess image - resize and convert to RGB
93
+ if pil_img.mode != 'RGB':
94
+ pil_img = pil_img.convert('RGB')
95
+ processed_img = pil_img.resize((224, 224))
96
+ processed_img.save(img_path)
97
+
98
+ # Create DataFrame for prediction
99
+ df = pandas.DataFrame({"image": [str(img_path)]})
100
+
101
+ # Get predictions
102
+ proba_df = PREDICTOR.predict_proba(df)
103
+
104
+ # Create pretty labels with probabilities
105
+ pretty_dict = {}
106
+ for col in proba_df.columns:
107
+ if isinstance(col, int) and col < 26:
108
+ label = f"Letter {CLASS_LABELS[col]}"
109
+ else:
110
+ label = str(col)
111
+ pretty_dict[label] = float(proba_df[col].iloc[0])
112
+
113
+ # Sort by probability (highest first)
114
+ pretty_dict = dict(sorted(pretty_dict.items(), key=lambda x: x[1], reverse=True))
115
+
116
+ # Cleanup
117
+ shutil.rmtree(tmpdir, ignore_errors=True)
118
+
119
+ return pretty_dict, processed_img
120
+
121
+ # Example sign language images
122
+ EXAMPLES = [
123
+ ["https://www.signingsavvy.com/images/words/alphabet/2/a1.jpg"],
124
+ ["https://www.signingsavvy.com/images/words/alphabet/2/b1.jpg"],
125
+ ["https://www.signingsavvy.com/images/words/alphabet/2/c1.jpg"]
126
+ ]
127
+
128
+ # Gradio UI
129
+ with gradio.Blocks(theme=gradio.themes.Soft()) as demo:
130
+ gradio.Markdown("# 🤟 Sign Language Recognition")
131
+ gradio.Markdown("""
132
+ This app uses an AutoGluon multimodal predictor to recognize American Sign Language (ASL) letters.
133
+
134
+ **How to use:**
135
+ 1. Upload a photo of a hand sign or use your webcam
136
+ 2. The model will predict which letter (A-Z) it represents
137
+ 3. View the top 5 predictions with confidence scores
138
+ """)
139
+
140
+ with gradio.Row():
141
+ with gradio.Column():
142
+ image_in = gradio.Image(
143
+ type="pil",
144
+ label="Upload hand sign image",
145
+ sources=["upload", "webcam"]
146
+ )
147
+ with gradio.Column():
148
+ processed_out = gradio.Image(
149
+ type="pil",
150
+ label="Preprocessed image (what model sees - 224x224)"
151
+ )
152
+
153
+ proba_pretty = gradio.Label(num_top_classes=5, label="Top 5 predictions")
154
+
155
+ # Update on image change
156
+ image_in.change(
157
+ fn=do_predict,
158
+ inputs=[image_in],
159
+ outputs=[proba_pretty, processed_out]
160
+ )
161
+
162
+ gradio.Examples(
163
+ examples=EXAMPLES,
164
+ inputs=[image_in],
165
+ label="Example ASL signs (click to try)",
166
+ examples_per_page=3,
167
+ cache_examples=False,
168
+ )
169
+
170
+ gradio.Markdown("""
171
+ ---
172
+ **Note:** This model recognizes static ASL letters (A-Z). For best results, use clear images with good lighting.
173
+ """)
174
+
175
+ if __name__ == "__main__":
176
+ demo.launch()