koush1ki commited on
Commit
21f817c
·
verified ·
1 Parent(s): 57b99fb

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +79 -190
app.py CHANGED
@@ -1,5 +1,30 @@
1
  import gradio as gr
2
  from huggingface_hub import InferenceClient
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3
 
4
  spotify_embed = """
5
  <iframe data-testid="embed-iframe"
@@ -17,194 +42,6 @@ picture-in-picture"
17
  loading="lazy"></iframe>
18
  """
19
 
20
-
21
- asl_html = """
22
- <div id="asl-wrapper" allow="camera; microphone" style="
23
- background:#fff0f6;
24
- border:1.5px solid #f3c4d7;
25
- border-radius:16px;
26
- padding:18px 20px 14px;
27
- margin-bottom:18px;
28
- font-family:sans-serif;
29
- ">
30
- <div style="font-weight:700;color:#9d4edd;font-size:1.05rem;margin-bottom:10px;">
31
- ASL Letter Signer
32
- </div>
33
-
34
- <div style="display:flex;gap:16px;align-items:flex-start;flex-wrap:wrap;">
35
- <div>
36
- <div id="asl-webcam" style="
37
- width:240px;
38
- height:180px;
39
- border-radius:10px;
40
- background:#000;
41
- border:2px solid #f8c8dc;
42
- overflow:hidden;
43
- "></div>
44
- <canvas id="asl-canvas" width="240" height="180" style="display:none;"></canvas>
45
- </div>
46
-
47
- <div style="flex:1;min-width:180px;">
48
- <div style="font-size:0.82rem;color:#7b2cbf;margin-bottom:4px;">Detected letter</div>
49
- <div id="asl-letter" style="
50
- font-size:3rem;font-weight:900;color:#9d4edd;
51
- background:#fff;border-radius:10px;border:1.5px solid #e0c3fc;
52
- width:64px;height:64px;display:flex;align-items:center;justify-content:center;
53
- margin-bottom:8px;">–</div>
54
-
55
- <div style="font-size:0.78rem;color:#7b2cbf;margin-bottom:3px;">Confidence</div>
56
- <div style="background:#f3c4d7;border-radius:8px;height:10px;width:100%;max-width:200px;margin-bottom:12px;">
57
- <div id="asl-conf-bar" style="height:10px;border-radius:8px;background:#ff8fab;width:0%;transition:width 0.2s;"></div>
58
- </div>
59
-
60
- <div style="font-size:0.82rem;color:#7b2cbf;margin-bottom:3px;">Current word</div>
61
- <div id="asl-word" style="
62
- font-size:1.4rem;font-weight:700;color:#5c5470;
63
- background:#fff;border:1.5px solid #f3c4d7;border-radius:8px;
64
- padding:4px 10px;min-width:120px;min-height:36px;
65
- letter-spacing:3px;margin-bottom:12px;"></div>
66
-
67
- <div style="display:flex;gap:8px;flex-wrap:wrap;">
68
- <button onclick="aslAddLetter()" style="background:#ffb3c6;color:#fff;border:none;border-radius:8px;padding:7px 14px;font-weight:600;cursor:pointer;">
69
- Add Letter
70
- </button>
71
- <button onclick="aslAddSpace()" style="background:#e0c3fc;color:#4a4a4a;border:none;border-radius:8px;padding:7px 14px;font-weight:600;cursor:pointer;">
72
- Space
73
- </button>
74
- <button onclick="aslSendWord()" style="background:#9d4edd;color:#fff;border:none;border-radius:8px;padding:7px 14px;font-weight:600;cursor:pointer;">
75
- Send
76
- </button>
77
- <button onclick="aslClear()" style="background:#fff;color:#c77dff;border:1.5px solid #e0c3fc;border-radius:8px;padding:7px 14px;font-weight:600;cursor:pointer;">
78
- Clear
79
- </button>
80
- </div>
81
-
82
- <div style="font-size:0.74rem;color:#cdb4db;margin-top:8px;">
83
- Tip: press Space to add letter, Enter to send word
84
- </div>
85
- </div>
86
- </div>
87
-
88
- <div id="asl-status" style="margin-top:10px;font-size:0.8rem;color:#c77dff;">
89
- Click Start Camera to begin.
90
- </div>
91
-
92
- <button onclick="initASL()" style="margin-top:8px;background:#9d4edd;color:#fff;border:none;border-radius:8px;padding:8px 18px;">
93
- 📷 Start Camera
94
- </button>
95
- </div>
96
-
97
- <script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs@latest/dist/tf.min.js"></script>
98
- <script src="https://cdn.jsdelivr.net/npm/@teachablemachine/image@latest/dist/teachablemachine-image.min.js"></script>
99
-
100
- <script>
101
- const MODEL_URL = "https://teachablemachine.withgoogle.com/models/4aHXkhLXo/";
102
-
103
- let tmModel, webcamObj;
104
- let currentLetter = "–";
105
- let currentWord = "";
106
- const videoContainer = document.getElementById("asl-webcam"); #new change, if breaks remove
107
- async function initASL() {
108
- const status = document.getElementById("asl-status");
109
- status.textContent = "Loading model...";
110
-
111
- const modelURL = MODEL_URL + "model.json";
112
- const metaURL = MODEL_URL + "metadata.json";
113
-
114
- tmModel = await tmImage.load(modelURL, metaURL);
115
-
116
- status.textContent = "Starting webcam...";
117
-
118
- webcamObj = new tmImage.Webcam(240, 180, true);
119
-
120
- await webcamObj.setup(); // must come first
121
- await webcamObj.play();
122
-
123
-
124
- if (!videoContainer) {
125
- console.error("ASL container missing");
126
- return;
127
- }
128
-
129
-
130
- videoContainer.innerHTML = "";
131
-
132
-
133
- await webcamObj.setup(); #new line
134
- await webcamObj.play(); #new code
135
-
136
- document.getElementById("asl-webcam").appendChild(webcamObj.canvas); #new code
137
- webcamObj.canvas.style.width = "240px";
138
- webcamObj.canvas.style.height = "180px";
139
- webcamObj.canvas.style.borderRadius = "10px";
140
-
141
- status.textContent = "Ready — start signing";
142
-
143
- loop();
144
- }
145
-
146
- async function loop() {
147
- webcamObj.update();
148
- const preds = await tmModel.predict(webcamObj.canvas);
149
-
150
- let best = preds.reduce((a,b) => a.probability > b.probability ? a : b);
151
-
152
- currentLetter = best.className;
153
-
154
- document.getElementById("asl-letter").textContent = currentLetter;
155
- document.getElementById("asl-conf-bar").style.width =
156
- Math.round(best.probability * 100) + "%";
157
-
158
- requestAnimationFrame(loop);
159
- }
160
-
161
- function aslAddLetter() {
162
- currentWord += currentLetter;
163
- document.getElementById("asl-word").textContent = currentWord;
164
- }
165
-
166
- function aslAddSpace() {
167
- currentWord += " ";
168
- document.getElementById("asl-word").textContent = currentWord;
169
- }
170
-
171
- function aslClear() {
172
- currentWord = "";
173
- document.getElementById("asl-word").textContent = "";
174
- }
175
-
176
- function aslSendWord() {
177
- const inputs = document.querySelectorAll("textarea");
178
- let chatInput = inputs[inputs.length - 1];
179
-
180
- const setter = Object.getOwnPropertyDescriptor(
181
- window.HTMLTextAreaElement.prototype,
182
- 'value'
183
- ).set;
184
-
185
- setter.call(chatInput, currentWord);
186
- chatInput.dispatchEvent(new Event('input', { bubbles: true }));
187
-
188
- setTimeout(() => {
189
- const btns = document.querySelectorAll("button");
190
- for (let b of btns) {
191
- if (b.textContent.toLowerCase().includes("submit") || b.querySelector("svg")) {
192
- b.click();
193
- break;
194
- }
195
- }
196
- }, 100);
197
-
198
- aslClear();
199
- }
200
-
201
- document.addEventListener("keydown", (e) => {
202
- if (e.code === "Space") aslAddLetter();
203
- if (e.code === "Enter") aslSendWord();
204
- });
205
- </script>
206
- """
207
-
208
  theme = gr.themes.Soft().set(
209
  body_background_fill="#fff7fb",
210
  block_background_fill="#ffffffcc",
@@ -240,7 +77,6 @@ SYSTEM_MESSAGES = {
240
  }
241
 
242
  def respond(message, history, mode):
243
-
244
  if mode is None:
245
  yield "Please select a mode first.", mode
246
  return
@@ -270,6 +106,20 @@ def respond(message, history, mode):
270
  yield response, mode
271
 
272
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
273
 
274
  with gr.Blocks(theme=theme) as demo:
275
 
@@ -300,7 +150,46 @@ with gr.Blocks(theme=theme) as demo:
300
  )
301
 
302
  gr.Markdown("### 🤟 ASL Input")
303
- gr.HTML(asl_html)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
304
 
305
  gr.Markdown("### 🎵 Music")
306
  gr.HTML(spotify_embed)
 
1
  import gradio as gr
2
  from huggingface_hub import InferenceClient
3
+ import numpy as np
4
+ from PIL import Image
5
+ import tflite_runtime.interpreter as tflite
6
+
7
+ # Load TFLite model at startup
8
+ interpreter = tflite.Interpreter(model_path="model.tflite")
9
+ interpreter.allocate_tensors()
10
+ input_details = interpreter.get_input_details()
11
+ output_details = interpreter.get_output_details()
12
+
13
+ # Load labels
14
+ with open("labels.txt", "r") as f:
15
+ labels = [line.strip().split(" ", 1)[-1] for line in f.readlines()]
16
+
17
+ def predict_asl(frame):
18
+ if frame is None:
19
+ return "–"
20
+ img = Image.fromarray(frame).resize((224, 224))
21
+ img_array = np.array(img, dtype=np.float32) / 255.0
22
+ img_array = np.expand_dims(img_array, axis=0)
23
+ interpreter.set_tensor(input_details[0]['index'], img_array)
24
+ interpreter.invoke()
25
+ predictions = interpreter.get_tensor(output_details[0]['index'])[0]
26
+ best_idx = int(np.argmax(predictions))
27
+ return labels[best_idx]
28
 
29
  spotify_embed = """
30
  <iframe data-testid="embed-iframe"
 
42
  loading="lazy"></iframe>
43
  """
44
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
45
  theme = gr.themes.Soft().set(
46
  body_background_fill="#fff7fb",
47
  block_background_fill="#ffffffcc",
 
77
  }
78
 
79
  def respond(message, history, mode):
 
80
  if mode is None:
81
  yield "Please select a mode first.", mode
82
  return
 
106
  yield response, mode
107
 
108
 
109
+ def add_letter(letter, word):
110
+ if letter and letter != "–":
111
+ return word + letter
112
+ return word
113
+
114
+ def add_space(word):
115
+ return word + " "
116
+
117
+ def clear_word():
118
+ return ""
119
+
120
+ def send_word(word):
121
+ return word, ""
122
+
123
 
124
  with gr.Blocks(theme=theme) as demo:
125
 
 
150
  )
151
 
152
  gr.Markdown("### 🤟 ASL Input")
153
+ with gr.Group():
154
+ gr.Markdown("*Sign a letter in front of your camera, then click Add Letter to build a word and Send to chat.*")
155
+ with gr.Row():
156
+ with gr.Column(scale=1):
157
+ asl_cam = gr.Image(
158
+ sources=["webcam"],
159
+ streaming=True,
160
+ label="Camera",
161
+ mirror_webcam=True,
162
+ height=300
163
+ )
164
+ with gr.Column(scale=1):
165
+ asl_detected = gr.Textbox(label="Detected Letter", interactive=False, value="–")
166
+ asl_word_box = gr.Textbox(label="Current Word", interactive=False, value="")
167
+ with gr.Row():
168
+ asl_add_btn = gr.Button("Add Letter", variant="primary")
169
+ asl_space_btn = gr.Button("Space", variant="secondary")
170
+ asl_clear_btn = gr.Button("Clear", variant="secondary")
171
+ asl_send_btn = gr.Button("Send to Chat ➤", variant="primary")
172
+
173
+ word_state = gr.State("")
174
+
175
+ asl_cam.stream(
176
+ fn=predict_asl,
177
+ inputs=[asl_cam],
178
+ outputs=[asl_detected]
179
+ )
180
+
181
+ asl_add_btn.click(fn=add_letter, inputs=[asl_detected, word_state], outputs=[word_state]).then(
182
+ fn=lambda w: w, inputs=[word_state], outputs=[asl_word_box]
183
+ )
184
+ asl_space_btn.click(fn=add_space, inputs=[word_state], outputs=[word_state]).then(
185
+ fn=lambda w: w, inputs=[word_state], outputs=[asl_word_box]
186
+ )
187
+ asl_clear_btn.click(fn=clear_word, outputs=[word_state]).then(
188
+ fn=lambda w: w, inputs=[word_state], outputs=[asl_word_box]
189
+ )
190
+ asl_send_btn.click(fn=send_word, inputs=[word_state], outputs=[chatbot.textbox, word_state]).then(
191
+ fn=lambda w: w, inputs=[word_state], outputs=[asl_word_box]
192
+ )
193
 
194
  gr.Markdown("### 🎵 Music")
195
  gr.HTML(spotify_embed)