lfolle commited on
Commit
2b21df1
Β·
verified Β·
1 Parent(s): 59431df

Upload folder using huggingface_hub

Browse files
Files changed (3) hide show
  1. app.py +19 -23
  2. assets/example_1.jpg +2 -2
  3. backend.py +7 -1
app.py CHANGED
@@ -32,20 +32,20 @@ DISCLAIMER = (
32
  # Predict function
33
  # ---------------------------------------------------------------------------
34
 
 
35
  def predict(image: np.ndarray):
36
  """Called by Gradio on button click or example selection."""
37
  if image is None:
38
  empty = np.zeros((64, 64, 3), dtype=np.uint8)
39
  return (
40
- empty, # annotated image
41
- *([empty, "–"] * 5), # 5Γ— (nail crop, score label)
42
- "–", # total
43
  "Please upload an image.",
44
  )
45
 
46
  result = backend.predict(image)
47
 
48
- outputs = [result["annotated_image"]]
49
  for nail_img, score in zip(result["nails"], result["napsi_scores"]):
50
  outputs.append(nail_img)
51
  outputs.append(str(score) if score >= 0 else "–")
@@ -68,7 +68,7 @@ with gr.Blocks(
68
  gr.Markdown(NAPSI_DESC)
69
  gr.Markdown(DISCLAIMER)
70
 
71
- # ── Top row: input + annotated hand at equal size ─────────────────────
72
  with gr.Row():
73
  with gr.Column(scale=1):
74
  image_input = gr.Image(
@@ -81,37 +81,34 @@ with gr.Blocks(
81
  gr.Examples(
82
  examples=[
83
  ["assets/example_1.jpg"],
84
- ["assets/example_2.jpg"],
85
- ["assets/example_3.jpg"],
86
  ],
87
  inputs=image_input,
88
  label="Example images",
89
  )
90
 
91
- with gr.Column(scale=1):
92
- annotated_out = gr.Image(
93
- label="Detected hand",
94
- type="numpy",
95
- interactive=False,
96
- )
97
-
98
  # ── Bottom rows: nail crops + scores ──────────────────────────────────
99
  with gr.Row():
100
- nail_images = [gr.Image(label=f, type="numpy", interactive=False, height=160) for f in FINGER_NAMES]
 
 
 
101
  with gr.Row():
102
- nail_scores = [gr.Textbox(label=f"NAPSI {f}", interactive=False) for f in FINGER_NAMES]
 
 
103
 
104
  with gr.Row():
105
- total_score = gr.Textbox(label="DeepNAPSI Total (one hand, 0–20)", interactive=False)
 
 
106
 
107
  error_box = gr.Textbox(label="Status", interactive=False, visible=True)
108
 
109
  # Wire outputs into a flat list matching predict() return order
110
- all_outputs = (
111
- [annotated_out]
112
- + [x for pair in zip(nail_images, nail_scores) for x in pair]
113
- + [total_score, error_box]
114
- )
115
 
116
  predict_btn.click(fn=predict, inputs=image_input, outputs=all_outputs)
117
 
@@ -125,4 +122,3 @@ if __name__ == "__main__":
125
  favicon_path="assets/favicon-32x32.png",
126
  theme=gr.themes.Soft(),
127
  )
128
-
 
32
  # Predict function
33
  # ---------------------------------------------------------------------------
34
 
35
+
36
  def predict(image: np.ndarray):
37
  """Called by Gradio on button click or example selection."""
38
  if image is None:
39
  empty = np.zeros((64, 64, 3), dtype=np.uint8)
40
  return (
41
+ *([empty, "–"] * 5), # 5Γ— (nail crop, score label)
42
+ "–", # total
 
43
  "Please upload an image.",
44
  )
45
 
46
  result = backend.predict(image)
47
 
48
+ outputs = []
49
  for nail_img, score in zip(result["nails"], result["napsi_scores"]):
50
  outputs.append(nail_img)
51
  outputs.append(str(score) if score >= 0 else "–")
 
68
  gr.Markdown(NAPSI_DESC)
69
  gr.Markdown(DISCLAIMER)
70
 
71
+ # ── Top row: input only (annotated hand preview removed) ──────────────
72
  with gr.Row():
73
  with gr.Column(scale=1):
74
  image_input = gr.Image(
 
81
  gr.Examples(
82
  examples=[
83
  ["assets/example_1.jpg"],
 
 
84
  ],
85
  inputs=image_input,
86
  label="Example images",
87
  )
88
 
 
 
 
 
 
 
 
89
  # ── Bottom rows: nail crops + scores ──────────────────────────────────
90
  with gr.Row():
91
+ nail_images = [
92
+ gr.Image(label=f, type="numpy", interactive=False, height=160)
93
+ for f in FINGER_NAMES
94
+ ]
95
  with gr.Row():
96
+ nail_scores = [
97
+ gr.Textbox(label=f"NAPSI {f}", interactive=False) for f in FINGER_NAMES
98
+ ]
99
 
100
  with gr.Row():
101
+ total_score = gr.Textbox(
102
+ label="DeepNAPSI Total (one hand, 0–20)", interactive=False
103
+ )
104
 
105
  error_box = gr.Textbox(label="Status", interactive=False, visible=True)
106
 
107
  # Wire outputs into a flat list matching predict() return order
108
+ all_outputs = [x for pair in zip(nail_images, nail_scores) for x in pair] + [
109
+ total_score,
110
+ error_box,
111
+ ]
 
112
 
113
  predict_btn.click(fn=predict, inputs=image_input, outputs=all_outputs)
114
 
 
122
  favicon_path="assets/favicon-32x32.png",
123
  theme=gr.themes.Soft(),
124
  )
 
assets/example_1.jpg CHANGED

Git LFS Details

  • SHA256: 70f8bc2543bd5a450f62c2b35aa1db280002ab8b2f9f89d6c76e3f9798e6b19c
  • Pointer size: 128 Bytes
  • Size of remote file: 131 Bytes

Git LFS Details

  • SHA256: 77ee8620048e6fd01d1fb21fbfb2020ab6cf7fe0d06ed385f21afbd86141b854
  • Pointer size: 131 Bytes
  • Size of remote file: 867 kB
backend.py CHANGED
@@ -8,6 +8,7 @@ Git LFS). If that file is absent it is downloaded from the HF Hub.
8
 
9
  from __future__ import annotations
10
 
 
11
  import os
12
  from pathlib import Path
13
  from typing import List
@@ -59,7 +60,12 @@ def _get_model_path() -> Path:
59
  "DeepNAPSIModel secret is set. Set one in the Space settings."
60
  )
61
  print(f"[backend] Downloading model from private repo {HF_REPO_ID} …")
62
- path = hf_hub_download(HF_REPO_ID, HF_FILENAME, token=token)
 
 
 
 
 
63
  return Path(path)
64
 
65
 
 
8
 
9
  from __future__ import annotations
10
 
11
+ import concurrent.futures
12
  import os
13
  from pathlib import Path
14
  from typing import List
 
60
  "DeepNAPSIModel secret is set. Set one in the Space settings."
61
  )
62
  print(f"[backend] Downloading model from private repo {HF_REPO_ID} …")
63
+ # Run inside a ThreadPoolExecutor so that huggingface_hub's internal asyncio
64
+ # event loop is isolated; avoids the harmless-but-noisy
65
+ # "Invalid file descriptor: -1" Python 3.12 GC warning on Space startup.
66
+ with concurrent.futures.ThreadPoolExecutor(max_workers=1) as pool:
67
+ future = pool.submit(hf_hub_download, HF_REPO_ID, HF_FILENAME, token=token)
68
+ path = future.result()
69
  return Path(path)
70
 
71