| |
| |
| """ |
| 视频可视化: |
| - 原视频检查:采样帧上画红色矩形框(线宽可见) |
| - 黑底 mask:采样帧填充白色 bbox 区域,其它帧纯黑 |
| - 编解码兜底:mp4v 打不开则自动降级到 XVID + .avi |
| """ |
|
|
| import cv2 |
| import numpy as np |
| from typing import List, Dict |
|
|
| RED = (0, 0, 255) |
| WHITE = (255, 255, 255) |
|
|
| def _to_xyxy(bbox, W, H): |
| x1, y1, x2, y2 = bbox |
| return int(round(x1 * W)), int(round(y1 * H)), int(round(x2 * W)), int(round(y2 * H)) |
|
|
| def _make_writer(path: str, W: int, H: int, fps: float): |
| fourcc = cv2.VideoWriter_fourcc(*'mp4v') |
| vw = cv2.VideoWriter(path, fourcc, fps, (W, H)) |
| if not vw.isOpened(): |
| |
| fourcc = cv2.VideoWriter_fourcc(*'XVID') |
| path = path.rsplit('.', 1)[0] + '.avi' |
| vw = cv2.VideoWriter(path, fourcc, fps, (W, H)) |
| return vw, path |
|
|
| def draw_inspection_video(src_path: str, out_path: str, sampled_idx: List[int], |
| tasks_json: Dict[str, List[Dict]], thickness: int = 4) -> None: |
| cap = cv2.VideoCapture(src_path) |
| if not cap.isOpened(): |
| raise RuntimeError(f"cannot open video: {src_path}") |
| W = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)) |
| H = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT)) |
| fps = cap.get(cv2.CAP_PROP_FPS) or 25.0 |
|
|
| vw, out_path = _make_writer(out_path, W, H, fps) |
|
|
| |
| bbox_by_frame = {} |
| for _, seq in tasks_json.items(): |
| for k, e in enumerate(seq): |
| if k >= len(sampled_idx): |
| break |
| bb = e.get("bbox") |
| if bb is None: |
| continue |
| frm = sampled_idx[k] |
| bbox_by_frame.setdefault(frm, []).append(bb) |
|
|
| cur = 0 |
| while True: |
| ok, frame = cap.read() |
| if not ok: |
| break |
| if cur in bbox_by_frame: |
| for bb in bbox_by_frame[cur]: |
| x1, y1, x2, y2 = _to_xyxy(bb, W, H) |
| cv2.rectangle(frame, (x1, y1), (x2, y2), RED, thickness) |
| vw.write(frame) |
| cur += 1 |
|
|
| cap.release() |
| vw.release() |
|
|
| def draw_mask_video(src_path: str, out_path: str, sampled_idx: List[int], |
| tasks_json: Dict[str, List[Dict]]) -> None: |
| cap = cv2.VideoCapture(src_path) |
| if not cap.isOpened(): |
| raise RuntimeError(f"cannot open video: {src_path}") |
| W = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)) |
| H = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT)) |
| fps = cap.get(cv2.CAP_PROP_FPS) or 25.0 |
| total = int(cap.get(cv2.CAP_PROP_FRAME_COUNT)) |
|
|
| vw, out_path = _make_writer(out_path, W, H, fps) |
| black = np.zeros((H, W, 3), dtype=np.uint8) |
|
|
| bbox_by_frame = {} |
| for _, seq in tasks_json.items(): |
| for k, e in enumerate(seq): |
| if k >= len(sampled_idx): |
| break |
| bb = e.get("bbox") |
| if bb is None: |
| continue |
| frm = sampled_idx[k] |
| bbox_by_frame.setdefault(frm, []).append(bb) |
|
|
| for cur in range(total): |
| frame = black.copy() |
| if cur in bbox_by_frame: |
| for bb in bbox_by_frame[cur]: |
| x1, y1, x2, y2 = _to_xyxy(bb, W, H) |
| |
| cv2.rectangle(frame, (x1, y1), (x2, y2), WHITE, thickness=-1) |
| vw.write(frame) |
|
|
| cap.release() |
| vw.release() |
|
|