JZVince commited on
Commit
b2d0be0
·
verified ·
1 Parent(s): 5963931

Upload 3 files

Browse files

fixed token issue

Files changed (3) hide show
  1. README.md +9 -8
  2. app.py +60 -24
  3. requirements.txt +2 -2
README.md CHANGED
@@ -1,15 +1,16 @@
1
  ---
2
- title: Spotpredator
3
- emoji: 💻
4
  colorFrom: green
5
- colorTo: green
6
  sdk: gradio
7
- sdk_version: 6.19.0
8
- python_version: '3.13'
9
  app_file: app.py
 
10
  pinned: false
11
- license: agpl-3.0
12
- short_description: Just a location to test my vision models on predators
13
  ---
14
 
15
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
 
 
 
1
  ---
2
+ title: SpotPredator Predator Detection
3
+ emoji: 🦅
4
  colorFrom: green
5
+ colorTo: blue
6
  sdk: gradio
 
 
7
  app_file: app.py
8
+ python_version: "3.11"
9
  pinned: false
 
 
10
  ---
11
 
12
+ # SpotPredator — predator_v2_fp16
13
+
14
+ Browser demo for an off-grid farm predator detector (coyote / fox / raptor).
15
+ Runs the TFLite model directly via LiteRT — no ultralytics required.
16
+ Drag in a field image to see detections.
app.py CHANGED
@@ -10,47 +10,72 @@ Create the Space:
10
  Or from CLI after `pip install huggingface_hub`:
11
  huggingface-cli repo create predator-demo --type space --space_sdk gradio
12
  """
 
13
  import numpy as np
14
  from PIL import Image, ImageDraw
15
  import gradio as gr
16
  from huggingface_hub import hf_hub_download, list_repo_files
17
 
18
  MODEL_REPO = "JZVince/predator_v2_fp16"
19
- CLASS_NAMES = ["coyote", "fox", "raptor"] # confirm this matches training order
 
 
 
 
20
 
21
  # ---- fetch the .tflite from the model repo (auto-detect the filename) --------
22
- tflite_name = next(f for f in list_repo_files(MODEL_REPO) if f.endswith(".tflite"))
23
- MODEL_PATH = hf_hub_download(MODEL_REPO, tflite_name)
 
24
 
 
25
  try:
26
- from tflite_runtime.interpreter import Interpreter
27
  except ImportError:
28
- from tensorflow.lite import Interpreter
29
- interp = Interpreter(model_path=MODEL_PATH); interp.allocate_tensors()
30
- INP = interp.get_input_details()[0]; OUT = interp.get_output_details()[0]
31
- IN_SIZE = int(INP["shape"][1]); NC = len(CLASS_NAMES)
 
 
 
 
 
 
32
 
33
  # ---- inference core (same verified decode as detect_tflite.py) ---------------
 
 
34
  def letterbox(img, new, color=(114, 114, 114)):
35
- w, h = img.size; gain = min(new/w, new/h)
 
36
  nw, nh = round(w*gain), round(h*gain)
37
  canvas = Image.new("RGB", (new, new), color)
38
  px, py = (new-nw)//2, (new-nh)//2
39
  canvas.paste(img.resize((nw, nh), Image.BILINEAR), (px, py))
40
  return canvas, gain, (px, py)
41
 
 
42
  def nms(boxes, scores, iou_thr=0.45):
43
- x1, y1, x2, y2 = boxes.T; areas = (x2-x1)*(y2-y1)
44
- order = scores.argsort()[::-1]; keep = []
 
 
45
  while order.size:
46
- i = order[0]; keep.append(i)
47
- xx1 = np.maximum(x1[i], x1[order[1:]]); yy1 = np.maximum(y1[i], y1[order[1:]])
48
- xx2 = np.minimum(x2[i], x2[order[1:]]); yy2 = np.minimum(y2[i], y2[order[1:]])
49
- w = np.maximum(0, xx2-xx1); h = np.maximum(0, yy2-yy1); inter = w*h
 
 
 
 
 
50
  iou = inter/(areas[i]+areas[order[1:]]-inter+1e-9)
51
  order = order[1:][iou <= iou_thr]
52
  return keep
53
 
 
54
  def detect(image, conf_thr=0.25, iou_thr=0.45):
55
  if image is None:
56
  return None, "Upload an image."
@@ -58,38 +83,49 @@ def detect(image, conf_thr=0.25, iou_thr=0.45):
58
  lb, gain, pad = letterbox(img, IN_SIZE)
59
  x = np.asarray(lb, np.float32)[None] / 255.0
60
  if INP["dtype"] == np.uint8:
61
- s, z = INP["quantization"]; x = (x/s + z).astype(np.uint8)
62
- interp.set_tensor(INP["index"], x); interp.invoke()
 
 
63
  y = interp.get_tensor(OUT["index"])
64
  if OUT["dtype"] == np.uint8:
65
- s, z = OUT["quantization"]; y = (y.astype(np.float32)-z)*s
 
66
  o = y[0]
67
  if o.shape[0] == 4 + NC:
68
  o = o.T
69
  xywh = o[:, :4].astype(np.float32).copy()
70
- cls = o[:, 4:4+NC]; cid = cls.argmax(1); conf = cls.max(1)
71
- m = conf >= conf_thr; xywh, conf, cid = xywh[m], conf[m], cid[m]
72
- draw = ImageDraw.Draw(img); lines = []
 
 
 
 
73
  colors = [(220, 70, 60), (240, 160, 40), (60, 130, 200)]
74
  if len(xywh):
75
  if xywh.max() <= 1.5:
76
  xywh *= IN_SIZE
77
  cx, cy, w, h = xywh.T
78
- x1 = (cx-w/2-pad[0])/gain; y1 = (cy-h/2-pad[1])/gain
79
- x2 = (cx+w/2-pad[0])/gain; y2 = (cy+h/2-pad[1])/gain
 
 
80
  xyxy = np.stack([x1, y1, x2, y2], 1)
81
  xyxy[:, [0, 2]] = xyxy[:, [0, 2]].clip(0, img.width)
82
  xyxy[:, [1, 3]] = xyxy[:, [1, 3]].clip(0, img.height)
83
  for c in np.unique(cid):
84
  idx = np.where(cid == c)[0]
85
  for k in nms(xyxy[idx], conf[idx], iou_thr):
86
- b = xyxy[idx][k]; col = colors[int(c) % 3]
 
87
  draw.rectangle(list(b), outline=col, width=3)
88
  draw.text((b[0]+3, max(0, b[1]-12)),
89
  f"{CLASS_NAMES[int(c)]} {conf[idx][k]:.2f}", fill=col)
90
  lines.append(f"{CLASS_NAMES[int(c)]}: {conf[idx][k]:.2f}")
91
  return img, ("\n".join(lines) if lines else "No predators detected.")
92
 
 
93
  demo = gr.Interface(
94
  fn=detect,
95
  inputs=[gr.Image(type="pil", label="Field image"),
 
10
  Or from CLI after `pip install huggingface_hub`:
11
  huggingface-cli repo create predator-demo --type space --space_sdk gradio
12
  """
13
+ import os
14
  import numpy as np
15
  from PIL import Image, ImageDraw
16
  import gradio as gr
17
  from huggingface_hub import hf_hub_download, list_repo_files
18
 
19
  MODEL_REPO = "JZVince/predator_v2_fp16"
20
+ # confirm this matches training order
21
+ CLASS_NAMES = ["coyote", "fox", "raptor"]
22
+
23
+ # Optional: set HF_TOKEN as a Space secret for higher rate limits / faster pulls.
24
+ HF_TOKEN = os.environ.get("spcae")
25
 
26
  # ---- fetch the .tflite from the model repo (auto-detect the filename) --------
27
+ tflite_name = next(f for f in list_repo_files(MODEL_REPO, token=HF_TOKEN)
28
+ if f.endswith(".tflite"))
29
+ MODEL_PATH = hf_hub_download(MODEL_REPO, tflite_name, token=HF_TOKEN)
30
 
31
+ # LiteRT is the successor to tflite-runtime; fall back through older runtimes.
32
  try:
33
+ from ai_edge_litert.interpreter import Interpreter
34
  except ImportError:
35
+ try:
36
+ from tflite_runtime.interpreter import Interpreter
37
+ except ImportError:
38
+ from tensorflow.lite import Interpreter
39
+ interp = Interpreter(model_path=MODEL_PATH)
40
+ interp.allocate_tensors()
41
+ INP = interp.get_input_details()[0]
42
+ OUT = interp.get_output_details()[0]
43
+ IN_SIZE = int(INP["shape"][1])
44
+ NC = len(CLASS_NAMES)
45
 
46
  # ---- inference core (same verified decode as detect_tflite.py) ---------------
47
+
48
+
49
  def letterbox(img, new, color=(114, 114, 114)):
50
+ w, h = img.size
51
+ gain = min(new/w, new/h)
52
  nw, nh = round(w*gain), round(h*gain)
53
  canvas = Image.new("RGB", (new, new), color)
54
  px, py = (new-nw)//2, (new-nh)//2
55
  canvas.paste(img.resize((nw, nh), Image.BILINEAR), (px, py))
56
  return canvas, gain, (px, py)
57
 
58
+
59
  def nms(boxes, scores, iou_thr=0.45):
60
+ x1, y1, x2, y2 = boxes.T
61
+ areas = (x2-x1)*(y2-y1)
62
+ order = scores.argsort()[::-1]
63
+ keep = []
64
  while order.size:
65
+ i = order[0]
66
+ keep.append(i)
67
+ xx1 = np.maximum(x1[i], x1[order[1:]])
68
+ yy1 = np.maximum(y1[i], y1[order[1:]])
69
+ xx2 = np.minimum(x2[i], x2[order[1:]])
70
+ yy2 = np.minimum(y2[i], y2[order[1:]])
71
+ w = np.maximum(0, xx2-xx1)
72
+ h = np.maximum(0, yy2-yy1)
73
+ inter = w*h
74
  iou = inter/(areas[i]+areas[order[1:]]-inter+1e-9)
75
  order = order[1:][iou <= iou_thr]
76
  return keep
77
 
78
+
79
  def detect(image, conf_thr=0.25, iou_thr=0.45):
80
  if image is None:
81
  return None, "Upload an image."
 
83
  lb, gain, pad = letterbox(img, IN_SIZE)
84
  x = np.asarray(lb, np.float32)[None] / 255.0
85
  if INP["dtype"] == np.uint8:
86
+ s, z = INP["quantization"]
87
+ x = (x/s + z).astype(np.uint8)
88
+ interp.set_tensor(INP["index"], x)
89
+ interp.invoke()
90
  y = interp.get_tensor(OUT["index"])
91
  if OUT["dtype"] == np.uint8:
92
+ s, z = OUT["quantization"]
93
+ y = (y.astype(np.float32)-z)*s
94
  o = y[0]
95
  if o.shape[0] == 4 + NC:
96
  o = o.T
97
  xywh = o[:, :4].astype(np.float32).copy()
98
+ cls = o[:, 4:4+NC]
99
+ cid = cls.argmax(1)
100
+ conf = cls.max(1)
101
+ m = conf >= conf_thr
102
+ xywh, conf, cid = xywh[m], conf[m], cid[m]
103
+ draw = ImageDraw.Draw(img)
104
+ lines = []
105
  colors = [(220, 70, 60), (240, 160, 40), (60, 130, 200)]
106
  if len(xywh):
107
  if xywh.max() <= 1.5:
108
  xywh *= IN_SIZE
109
  cx, cy, w, h = xywh.T
110
+ x1 = (cx-w/2-pad[0])/gain
111
+ y1 = (cy-h/2-pad[1])/gain
112
+ x2 = (cx+w/2-pad[0])/gain
113
+ y2 = (cy+h/2-pad[1])/gain
114
  xyxy = np.stack([x1, y1, x2, y2], 1)
115
  xyxy[:, [0, 2]] = xyxy[:, [0, 2]].clip(0, img.width)
116
  xyxy[:, [1, 3]] = xyxy[:, [1, 3]].clip(0, img.height)
117
  for c in np.unique(cid):
118
  idx = np.where(cid == c)[0]
119
  for k in nms(xyxy[idx], conf[idx], iou_thr):
120
+ b = xyxy[idx][k]
121
+ col = colors[int(c) % 3]
122
  draw.rectangle(list(b), outline=col, width=3)
123
  draw.text((b[0]+3, max(0, b[1]-12)),
124
  f"{CLASS_NAMES[int(c)]} {conf[idx][k]:.2f}", fill=col)
125
  lines.append(f"{CLASS_NAMES[int(c)]}: {conf[idx][k]:.2f}")
126
  return img, ("\n".join(lines) if lines else "No predators detected.")
127
 
128
+
129
  demo = gr.Interface(
130
  fn=detect,
131
  inputs=[gr.Image(type="pil", label="Field image"),
requirements.txt CHANGED
@@ -1,5 +1,5 @@
1
  gradio
2
  numpy
3
  pillow
4
- tensorflow-cpu
5
- huggingface_hub
 
1
  gradio
2
  numpy
3
  pillow
4
+ ai-edge-litert
5
+ huggingface_hub