Zhen Ye Claude Opus 4.6 (1M context) commited on
Commit
6a3e49a
·
1 Parent(s): 61b921a

feat: hide class labels on non-mission-relevant objects in rendered video

Browse files

Non-relevant objects now show only a gray bbox/mask with no label text.
Mission-relevant objects keep their red color and visible class label.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

Files changed (1) hide show
  1. inference.py +29 -13
inference.py CHANGED
@@ -144,20 +144,27 @@ _COLOR_NOT_RELEVANT = (128, 128, 128) # gray
144
  def _mission_colors_for_dets(
145
  dets: list,
146
  verdicts: Dict[str, bool],
147
- ) -> Optional[List[Tuple[int, int, int]]]:
148
- """Return per-detection BGR colors based on mission verdicts, or None if no verdicts."""
 
 
 
149
  if not verdicts:
150
- return None
151
  colors = []
 
152
  for d in dets:
153
  tid = d.get("track_id")
154
  if tid and tid in verdicts:
155
- colors.append(_COLOR_MISSION_RELEVANT if verdicts[tid] else _COLOR_NOT_RELEVANT)
 
 
156
  else:
157
- # Unassessed — use default hash color
158
  label = d.get("label", "obj")
159
  colors.append(_color_for_label(label))
160
- return colors
 
161
 
162
 
163
  def draw_boxes(
@@ -167,6 +174,7 @@ def draw_boxes(
167
  queries: Optional[Sequence[str]] = None,
168
  label_names: Optional[Sequence[str]] = None,
169
  colors: Optional[Sequence[Tuple[int, int, int]]] = None,
 
170
  ) -> np.ndarray:
171
  output = frame.copy()
172
  if boxes is None:
@@ -188,7 +196,8 @@ def draw_boxes(
188
  else:
189
  color = (128, 128, 128) if not label else _color_for_label(label)
190
  cv2.rectangle(output, (x1, y1), (x2, y2), color, thickness=2)
191
- if label:
 
192
  font = cv2.FONT_HERSHEY_SIMPLEX
193
  font_scale = 0.6
194
  thickness = 2
@@ -219,6 +228,7 @@ def draw_masks(
219
  alpha: float = 0.65,
220
  labels: Optional[Sequence[str]] = None,
221
  colors: Optional[Sequence[Tuple[int, int, int]]] = None,
 
222
  ) -> np.ndarray:
223
  output = frame.copy()
224
  if masks is None or len(masks) == 0:
@@ -248,8 +258,9 @@ def draw_masks(
248
  )
249
  if contours:
250
  cv2.drawContours(output, contours, -1, color, thickness=2)
251
- # Only draw label text when explicit labels were provided
252
- if label:
 
253
  coords = np.column_stack(np.where(mask_bool))
254
  if coords.size:
255
  y, x = coords[0]
@@ -962,10 +973,11 @@ def run_inference(
962
  display_labels = [d.get('label', 'obj') for d in dets]
963
  # Apply mission-relevance colors (red/gray) if verdicts available
964
  det_colors = None
 
965
  if job_id:
966
  verdicts = get_job_storage().get_mission_verdicts(job_id)
967
- det_colors = _mission_colors_for_dets(dets, verdicts)
968
- p_frame = draw_boxes(p_frame, display_boxes, label_names=display_labels, colors=det_colors)
969
 
970
  writer.write(p_frame)
971
 
@@ -1108,6 +1120,7 @@ def _gsam2_render_frame(
1108
  masks_list: List[np.ndarray] = []
1109
  mask_labels: List[str] = []
1110
  mask_colors: Optional[List[Tuple[int, int, int]]] = None if not mission_verdicts else []
 
1111
 
1112
  for obj_id, obj_info in frame_objects.items():
1113
  mask = obj_info.mask
@@ -1128,13 +1141,16 @@ def _gsam2_render_frame(
1128
  if mask_colors is not None:
1129
  tid = str(obj_id)
1130
  if tid in mission_verdicts:
1131
- mask_colors.append(_COLOR_MISSION_RELEVANT if mission_verdicts[tid] else _COLOR_NOT_RELEVANT)
 
 
1132
  else:
1133
  mask_colors.append(_color_for_label(label or f"object_{obj_id}"))
 
1134
 
1135
  if masks_list:
1136
  # Draw masks with labels — no bboxes for segmentation mode
1137
- frame = draw_masks(frame, np.stack(masks_list), labels=mask_labels, colors=mask_colors)
1138
 
1139
  return frame
1140
 
 
144
  def _mission_colors_for_dets(
145
  dets: list,
146
  verdicts: Dict[str, bool],
147
+ ) -> Tuple[Optional[List[Tuple[int, int, int]]], Optional[List[bool]]]:
148
+ """Return per-detection BGR colors and hide_labels flags based on mission verdicts.
149
+
150
+ Returns (None, None) if no verdicts available yet.
151
+ """
152
  if not verdicts:
153
+ return None, None
154
  colors = []
155
+ hide = []
156
  for d in dets:
157
  tid = d.get("track_id")
158
  if tid and tid in verdicts:
159
+ relevant = verdicts[tid]
160
+ colors.append(_COLOR_MISSION_RELEVANT if relevant else _COLOR_NOT_RELEVANT)
161
+ hide.append(not relevant)
162
  else:
163
+ # Unassessed — use default hash color, show label
164
  label = d.get("label", "obj")
165
  colors.append(_color_for_label(label))
166
+ hide.append(False)
167
+ return colors, hide
168
 
169
 
170
  def draw_boxes(
 
174
  queries: Optional[Sequence[str]] = None,
175
  label_names: Optional[Sequence[str]] = None,
176
  colors: Optional[Sequence[Tuple[int, int, int]]] = None,
177
+ hide_labels: Optional[Sequence[bool]] = None,
178
  ) -> np.ndarray:
179
  output = frame.copy()
180
  if boxes is None:
 
196
  else:
197
  color = (128, 128, 128) if not label else _color_for_label(label)
198
  cv2.rectangle(output, (x1, y1), (x2, y2), color, thickness=2)
199
+ should_hide = hide_labels is not None and idx < len(hide_labels) and hide_labels[idx]
200
+ if label and not should_hide:
201
  font = cv2.FONT_HERSHEY_SIMPLEX
202
  font_scale = 0.6
203
  thickness = 2
 
228
  alpha: float = 0.65,
229
  labels: Optional[Sequence[str]] = None,
230
  colors: Optional[Sequence[Tuple[int, int, int]]] = None,
231
+ hide_labels: Optional[Sequence[bool]] = None,
232
  ) -> np.ndarray:
233
  output = frame.copy()
234
  if masks is None or len(masks) == 0:
 
258
  )
259
  if contours:
260
  cv2.drawContours(output, contours, -1, color, thickness=2)
261
+ # Only draw label text when explicit labels were provided and not hidden
262
+ should_hide = hide_labels is not None and idx < len(hide_labels) and hide_labels[idx]
263
+ if label and not should_hide:
264
  coords = np.column_stack(np.where(mask_bool))
265
  if coords.size:
266
  y, x = coords[0]
 
973
  display_labels = [d.get('label', 'obj') for d in dets]
974
  # Apply mission-relevance colors (red/gray) if verdicts available
975
  det_colors = None
976
+ det_hide = None
977
  if job_id:
978
  verdicts = get_job_storage().get_mission_verdicts(job_id)
979
+ det_colors, det_hide = _mission_colors_for_dets(dets, verdicts)
980
+ p_frame = draw_boxes(p_frame, display_boxes, label_names=display_labels, colors=det_colors, hide_labels=det_hide)
981
 
982
  writer.write(p_frame)
983
 
 
1120
  masks_list: List[np.ndarray] = []
1121
  mask_labels: List[str] = []
1122
  mask_colors: Optional[List[Tuple[int, int, int]]] = None if not mission_verdicts else []
1123
+ mask_hide: Optional[List[bool]] = None if not mission_verdicts else []
1124
 
1125
  for obj_id, obj_info in frame_objects.items():
1126
  mask = obj_info.mask
 
1141
  if mask_colors is not None:
1142
  tid = str(obj_id)
1143
  if tid in mission_verdicts:
1144
+ relevant = mission_verdicts[tid]
1145
+ mask_colors.append(_COLOR_MISSION_RELEVANT if relevant else _COLOR_NOT_RELEVANT)
1146
+ mask_hide.append(not relevant)
1147
  else:
1148
  mask_colors.append(_color_for_label(label or f"object_{obj_id}"))
1149
+ mask_hide.append(False)
1150
 
1151
  if masks_list:
1152
  # Draw masks with labels — no bboxes for segmentation mode
1153
+ frame = draw_masks(frame, np.stack(masks_list), labels=mask_labels, colors=mask_colors, hide_labels=mask_hide)
1154
 
1155
  return frame
1156