我们可以通过以下几种方法实现:
1. 使用 ROI (Region of Interest) 蒙版方法import cv2 import numpy as np from ultralytics import YOLO # 加载YOLO模型 model = YOLO('yolov8n.pt') # 创建蒙版 def create_mask(frame_shape, points): mask = np.zeros(frame_shape[:2], dtype=np.uint8) # 将点转换为numpy数组 points = np.array(points, dtype=np.int32) # 填充多边形区域 cv2.fillPoly(mask, [points], 255) return mask # 视频处理 def process_video(video_path, roi_points): cap = cv2.VideoCapture(video_path) # 获取第一帧来创建蒙版 ret, frame = cap.read() if not ret: return # 创建ROI蒙版 mask = create_mask(frame.shape, roi_points) while True: ret, frame = cap.read() if not ret: break # 应用蒙版 masked_frame = cv2.bitwise_and(frame, frame, mask=mask) # YOLO检测 results = model(masked_frame) # 处理检测结果 for r in results: boxes = r.boxes for box in boxes: # 获取边界框坐标 x1, y1, x2, y2 = box.xyxy[0] x1, y1, x2, y2 = int(x1), int(y1), int(x2), int(y2) # 检查边界框是否在ROI内 box_center = ((x1 + x2) // 2, (y1 + y2) // 2) if mask[box_center[1], box_center[0]] > 0: # 绘制边界框 cv2.rectangle(frame, (x1, y1), (x2, y2), (0, 255, 0), 2) # 显示类别和置信度 conf = box.conf[0] cls = box.cls[0] label = f'{model.names[int(cls)]} {conf:.2f}' cv2.putText(frame, label, (x1, y1 - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 2) # 绘制ROI区域 cv2.polylines(frame, [roi_points], True, (0, 0, 255), 2) # 显示结果 cv2.imshow('YOLO with ROI', frame) if cv2.waitKey(1) & 0xFF == ord('q'): break cap.release() cv2.destroyAllWindows() # 使用示例 if __name__ == "__main__": # 定义ROI区域的点(根据需要修改坐标) roi_points = np.array([ [100, 100], # 左上 [500, 100], # 右上 [500, 400], # 右下 [100, 400] # 左下 ], dtype=np.int32) # 处理视频 video_path = "path/to/your/video.mp4" process_video(video_path, roi_points)2. 使用交互式ROI选择
import cv2 import numpy as np from ultralytics import YOLO class ROISelector: def __init__(self, window_name): self.window_name = window_name self.points = [] self.drawing = False def mouse_callback(self, event, x, y, flags, param): if event == cv2.EVENT_LBUTTONDOWN: self.points.append([x, y]) self.drawing = True elif event == cv2.EVENT_MOUSEMOVE and self.drawing: frame_copy = param.copy() points = np.array(self.points + [[x, y]], dtype=np.int32) cv2.polylines(frame_copy, [points], False, (0, 255, 0), 2) cv2.imshow(self.window_name, frame_copy) elif event == cv2.EVENT_LBUTTONUP: self.points.append([x, y]) self.drawing = False def select_roi(self, frame): cv2.imshow(self.window_name, frame) cv2.setMouseCallback(self.window_name, self.mouse_callback, frame) while True: key = cv2.waitKey(1) & 0xFF if key == ord('c'): # 完成选择 break elif key == ord('r'): # 重置选择 self.points = [] cv2.imshow(self.window_name, frame) return np.array(self.points, dtype=np.int32) def main(): # 加载YOLO模型 model = YOLO('yolov8n.pt') # 打开视频 video_path = "path/to/your/video.mp4" cap = cv2.VideoCapture(video_path) # 读取第一帧用于ROI选择 ret, frame = cap.read() if not ret: return # 选择ROI roi_selector = ROISelector('Select ROI') print("请用鼠标选择ROI区域点,按'c'确认,'r'重置") roi_points = roi_selector.select_roi(frame) # 创建蒙版 mask = np.zeros(frame.shape[:2], dtype=np.uint8) cv2.fillPoly(mask, [roi_points], 255) # 处理视频 while True: ret, frame = cap.read() if not ret: break # 应用蒙版 masked_frame = cv2.bitwise_and(frame, frame, mask=mask) # YOLO检测 results = model(masked_frame) # 统计计数 count_dict = {} # 处理检测结果 for r in results: boxes = r.boxes for box in boxes: x1, y1, x2, y2 = map(int, box.xyxy[0]) # 检查中心点是否在ROI内 center_x = (x1 + x2) // 2 center_y = (y1 + y2) // 2 if mask[center_y, center_x] > 0: cls = int(box.cls[0]) conf = float(box.conf[0]) # 更新计数 class_name = model.names[cls] count_dict[class_name] = count_dict.get(class_name, 0) + 1 # 绘制边界框和标签 cv2.rectangle(frame, (x1, y1), (x2, y2), (0, 255, 0), 2) label = f'{class_name} {conf:.2f}' cv2.putText(frame, label, (x1, y1-10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 2) # 绘制ROI区域 cv2.polylines(frame, [roi_points], True, (0, 0, 255), 2) # 显示计数结果 y_offset = 30 for class_name, count in count_dict.items(): cv2.putText(frame, f'{class_name}: {count}', (10, y_offset), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (255, 0, 0), 2) y_offset += 30 # 显示结果 cv2.imshow('YOLO Detection with ROI', frame) if cv2.waitKey(1) & 0xFF == ord('q'): break cap.release() cv2.destroyAllWindows() if __name__ == "__main__": main()主要功能和特点
ROI区域选择:
可以通过预定义坐标点设置ROI。或使用交互式界面手动选择ROI区域。支持多边形区域选择。检测过滤:
只统计ROI区域内的目标。使用目标中心点判断是否在ROI内。过滤掉ROI外的检测结果。可视化:
显示ROI边界。显示检测到的目标边界框。显示类别和置信度。显示各类别的计数统计。实时统计:
统计ROI内各类别的数量。实时显示统计结果。使用方法预定义ROI方式:
# 定义ROI点坐标 roi_points = np.array([ [x1, y1], [x2, y2], [x3, y3], [x4, y4] ], dtype=np.int32) # 处理视频 process_video("video.mp4", roi_points)
交互式选择ROI:
# 运行主程序 main() # 使用鼠标点击选择ROI区域点 # 按'c'确认选择 # 按'r'重置选择 # 按'q'退出程序这个实现方案可以帮助你:准确统计特定区域内的目标。避免区域外干扰。提供直观的可视化结果。灵活配置检测区域。
网友回复