import os import cv2 import numpy as np from datetime import datetime from ultralytics import YOLO DEFAULT_YOLOV8S_SEG_MODEL = './models/yolov8s-seg.pt' def get_center_distance(box, image_center): x1, y1, x2, y2 = box box_center = ((x1 + x2) / 2, (y1 + y2) / 2) return np.linalg.norm(np.array(box_center) - np.array(image_center)) def generate_mask_from_first_frame(video_path, filter_type:str = 'dist',mask_type:str="array",mask_file_path:str=None): """ 获取视频第一帧的 人像 MASK: filter_type: dist 距离 画面中心最近的人; default box : 画面中面积最大的人; mask_type : array: 直接返回 np.array ; default file:保存成mask_file_path ,返回mask_file_path """ if not os.path.exists(video_path): raise FileNotFoundError(f"视频文件不存在:{video_path}") cap = cv2.VideoCapture(video_path) ret, frame = cap.read() cap.release() if not ret: raise RuntimeError("无法读取视频第一帧") height, width, _ = frame.shape image_center = (width / 2, height / 2) print(os.path.exists(DEFAULT_YOLOV8S_SEG_MODEL)) model = YOLO(DEFAULT_YOLOV8S_SEG_MODEL) # 或 yolov8s-seg.pt,体积更大但更准 # 3. 进行人形检测+分割 results = model(frame)[0] # 筛选出所有类别为“person”的目标 person_masks = [] for i, cls in enumerate(results.boxes.cls): if int(cls) == 0: # class 0 是 "person" box = results.boxes.xyxy[i].cpu().numpy() # [x1, y1, x2, y2] mask = results.masks.data[i].cpu().numpy() dist = get_center_distance(box, image_center) box_area = (box[2] - box[0]) * (box[3] - box[1]) person_masks.append((dist, box_area, mask)) if not person_masks: return None # 4. 取距离中心最近的人形 if filter_type=="box": person_masks.sort(key=lambda x: x[1], reverse=True) else: person_masks.sort(key=lambda x: x[0]) best_mask = person_masks[0][2] best_mask_resized = cv2.resize(best_mask, (width, height), interpolation=cv2.INTER_NEAREST) if mask_type == "file": if not mask_file_path: now_str = datetime.now().strftime("%Y%m%d_%H%M%S") mask_file_path =f"./temp/{now_str}.png" mask_img = (best_mask_resized * 255).astype(np.uint8) cv2.imwrite(mask_file_path, mask_img) return mask_file_path else: mask = (best_mask_resized * 255).astype(np.uint8) return mask