mastefan commited on
Commit
9fc6edd
·
verified ·
1 Parent(s): df98de5

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +54 -12
app.py CHANGED
@@ -40,7 +40,7 @@ AG_REPO_ID = "emkessle/2024-24679-fencing-touch-predictor"
40
  AG_ZIP_NAME = "autogluon_predictor_dir.zip"
41
 
42
  FRAME_SKIP = 2
43
- KEEP_CONF = 0.80
44
  YOLO_CONF = 0.25
45
  YOLO_IOU = 0.50
46
  CLIP_PAD_S = 2.0
@@ -128,34 +128,76 @@ def isolate_scoreboard_color(frame_bgr: np.ndarray,
128
  conf: float = YOLO_CONF,
129
  iou: float = YOLO_IOU,
130
  keep_conf: float = KEEP_CONF,
131
- debug: bool = DEBUG_MODE,
132
  frame_id: int = None) -> np.ndarray:
133
- """Grayscale everything except the largest YOLO box ≥ keep_conf."""
 
 
 
 
 
 
 
134
  H, W = frame_bgr.shape[:2]
 
 
135
  gray = cv2.cvtColor(frame_bgr, cv2.COLOR_BGR2GRAY)
136
  gray = cv2.cvtColor(gray, cv2.COLOR_GRAY2BGR)
137
 
 
 
 
138
  chosen_box = None
139
  res = yolo().predict(frame_bgr, conf=conf, iou=iou, verbose=False)
140
  if len(res):
141
  r = res[0]
142
  if getattr(r, "boxes", None) is not None and len(r.boxes) > 0:
143
- boxes = r.boxes.xyxy.cpu().numpy()
144
  scores = r.boxes.conf.cpu().numpy()
145
- valid = [(b, s) for b, s in zip(boxes, scores) if float(s) >= keep_conf]
146
- if valid:
147
- chosen_box, _ = max(valid, key=lambda bs: (bs[0][2]-bs[0][0])*(bs[0][3]-bs[0][1]))
148
- x1, y1, x2, y2 = [int(v) for v in chosen_box]
149
- gray[y1:y2, x1:x2] = frame_bgr[y1:y2, x1:x2]
150
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
151
  if debug and frame_id is not None:
152
  dbg = gray.copy()
153
  if chosen_box is not None:
154
- x1, y1, x2, y2 = [int(v) for v in chosen_box]
155
- cv2.rectangle(dbg, (x1, y1), (x2, y2), (0,255,0), 2)
156
- cv2.imwrite(str(DEBUG_DIR / f"frame_{frame_id:06d}.jpg"), dbg)
 
 
 
157
  return gray
158
 
 
159
  def _count_color_pixels(rgb, ch):
160
  R, G, B = rgb[:,:,0], rgb[:,:,1], rgb[:,:,2]
161
  if ch==0: mask=(R>150)&(R>1.2*G)&(R>1.2*B)
 
40
  AG_ZIP_NAME = "autogluon_predictor_dir.zip"
41
 
42
  FRAME_SKIP = 2
43
+ KEEP_CONF = 0.85
44
  YOLO_CONF = 0.25
45
  YOLO_IOU = 0.50
46
  CLIP_PAD_S = 2.0
 
128
  conf: float = YOLO_CONF,
129
  iou: float = YOLO_IOU,
130
  keep_conf: float = KEEP_CONF,
131
+ debug: bool = False,
132
  frame_id: int = None) -> np.ndarray:
133
+ """
134
+ Improved version:
135
+ - Choose the largest bbox among candidates meeting confidence.
136
+ - Primary threshold: >= max(0.80, keep_conf)
137
+ - Fallback threshold: >= (primary - 0.05)
138
+ - Entire chosen bbox is restored to color; everything else is grayscale.
139
+ - Rejects low-saturation ROIs (flat/neutral areas).
140
+ """
141
  H, W = frame_bgr.shape[:2]
142
+
143
+ # Start fully grayscale
144
  gray = cv2.cvtColor(frame_bgr, cv2.COLOR_BGR2GRAY)
145
  gray = cv2.cvtColor(gray, cv2.COLOR_GRAY2BGR)
146
 
147
+ primary_thr = max(0.80, keep_conf)
148
+ fallback_thr = max(0.7, primary_thr - 0.05)
149
+
150
  chosen_box = None
151
  res = yolo().predict(frame_bgr, conf=conf, iou=iou, verbose=False)
152
  if len(res):
153
  r = res[0]
154
  if getattr(r, "boxes", None) is not None and len(r.boxes) > 0:
155
+ boxes = r.boxes.xyxy.cpu().numpy()
156
  scores = r.boxes.conf.cpu().numpy()
157
+ candidates = list(zip(boxes, scores))
 
 
 
 
158
 
159
+ # Prefer largest box meeting primary threshold
160
+ strong = [(b, s) for (b, s) in candidates if float(s) >= primary_thr]
161
+ if strong:
162
+ chosen_box, _ = max(strong, key=lambda bs: (bs[0][2]-bs[0][0]) * (bs[0][3]-bs[0][1]))
163
+ else:
164
+ # Fallback: largest box meeting fallback threshold
165
+ medium = [(b, s) for (b, s) in candidates if float(s) >= fallback_thr]
166
+ if medium:
167
+ chosen_box, _ = max(medium, key=lambda bs: (bs[0][2]-bs[0][0]) * (bs[0][3]-bs[0][1]))
168
+
169
+ if chosen_box is not None:
170
+ x1, y1, x2, y2 = [int(round(v)) for v in chosen_box]
171
+ x1, y1 = max(0, x1), max(0, y1)
172
+ x2, y2 = min(W-1, x2), min(H-1, y2)
173
+
174
+ if x2 > x1 and y2 > y1:
175
+ # Single safeguard: reject very low-saturation ROIs
176
+ roi_color = frame_bgr[y1:y2, x1:x2]
177
+ if roi_color.size > 0:
178
+ hsv = cv2.cvtColor(roi_color, cv2.COLOR_BGR2HSV)
179
+ sat_mean = hsv[:, :, 1].mean()
180
+ if sat_mean < 25:
181
+ print(f"[WARN] Rejected bbox due to low saturation (mean={sat_mean:.1f})")
182
+ chosen_box = None
183
+
184
+ # If accepted, restore whole bbox to color
185
+ if chosen_box is not None:
186
+ gray[y1:y2, x1:x2] = frame_bgr[y1:y2, x1:x2]
187
+
188
+ # Optional debug save
189
  if debug and frame_id is not None:
190
  dbg = gray.copy()
191
  if chosen_box is not None:
192
+ x1, y1, x2, y2 = [int(round(v)) for v in chosen_box]
193
+ cv2.rectangle(dbg, (x1, y1), (x2, y2), (0, 255, 0), 2)
194
+ out_path = DEBUG_DIR / f"frame_{frame_id:06d}.jpg"
195
+ cv2.imwrite(str(out_path), dbg)
196
+ print(f"[DEBUG] Saved debug frame → {out_path}")
197
+
198
  return gray
199
 
200
+
201
  def _count_color_pixels(rgb, ch):
202
  R, G, B = rgb[:,:,0], rgb[:,:,1], rgb[:,:,2]
203
  if ch==0: mask=(R>150)&(R>1.2*G)&(R>1.2*B)