Zhen Ye Claude Opus 4.6 (1M context) commited on
Commit
a2f4d4e
·
1 Parent(s): c51e2e9

fix: handle degenerate bbox and unhandled exceptions in inspection frame endpoint

Browse files

Cast bbox coordinates to int in crop_frame to prevent numpy float indexing errors.
Add error handling for ValueError/OSError in the /inspect/frame endpoint to return
422 instead of 500 when frame extraction or cropping fails.

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

Files changed (2) hide show
  1. inspection/frames.py +1 -1
  2. inspection/router.py +16 -2
inspection/frames.py CHANGED
@@ -77,7 +77,7 @@ def crop_frame(
77
  Returns:
78
  Cropped HxWx3 BGR numpy array.
79
  """
80
- x1, y1, x2, y2 = bbox
81
  if x2 <= x1 or y2 <= y1:
82
  raise ValueError(
83
  f"Invalid bbox: [{x1}, {y1}, {x2}, {y2}] — must have x2 > x1 and y2 > y1"
 
77
  Returns:
78
  Cropped HxWx3 BGR numpy array.
79
  """
80
+ x1, y1, x2, y2 = int(bbox[0]), int(bbox[1]), int(bbox[2]), int(bbox[3])
81
  if x2 <= x1 or y2 <= y1:
82
  raise ValueError(
83
  f"Invalid bbox: [{x1}, {y1}, {x2}, {y2}] — must have x2 > x1 and y2 > y1"
inspection/router.py CHANGED
@@ -99,7 +99,10 @@ async def get_frame(
99
  _validate_frame_idx(input_path, frame_idx)
100
 
101
  # Extract frame in thread pool (cv2 seek can block)
102
- frame = await asyncio.to_thread(extract_frame, input_path, frame_idx)
 
 
 
103
 
104
  # Optionally crop to track bbox
105
  if track_id is not None:
@@ -110,7 +113,18 @@ async def get_frame(
110
  instance_id = _parse_track_id(track_id)
111
  target = _find_track(tracks, instance_id, track_id)
112
  if target and "bbox" in target:
113
- frame = crop_frame(frame, target["bbox"], padding=padding)
 
 
 
 
 
 
 
 
 
 
 
114
  else:
115
  raise HTTPException(
116
  status_code=404,
 
99
  _validate_frame_idx(input_path, frame_idx)
100
 
101
  # Extract frame in thread pool (cv2 seek can block)
102
+ try:
103
+ frame = await asyncio.to_thread(extract_frame, input_path, frame_idx)
104
+ except (ValueError, OSError) as exc:
105
+ raise HTTPException(status_code=422, detail=str(exc))
106
 
107
  # Optionally crop to track bbox
108
  if track_id is not None:
 
113
  instance_id = _parse_track_id(track_id)
114
  target = _find_track(tracks, instance_id, track_id)
115
  if target and "bbox" in target:
116
+ bbox = target["bbox"]
117
+ # Validate bbox is non-degenerate before cropping
118
+ x1, y1, x2, y2 = [int(c) for c in bbox]
119
+ if x2 <= x1 or y2 <= y1:
120
+ raise HTTPException(
121
+ status_code=422,
122
+ detail=f"Track {track_id} has a degenerate bbox [{x1},{y1},{x2},{y2}] at frame {frame_idx}.",
123
+ )
124
+ try:
125
+ frame = crop_frame(frame, [x1, y1, x2, y2], padding=padding)
126
+ except ValueError as exc:
127
+ raise HTTPException(status_code=422, detail=str(exc))
128
  else:
129
  raise HTTPException(
130
  status_code=404,