如何使用YOLOv5检测网络摄像头特定区域内的目标
完全可以基于YOLOv5实现你要的「网络摄像头画面下,以model1输出边界框为model2专属检测区域」的两级检测逻辑,不需要改动模型本身结构,仅需在帧推理流程中增加区域裁剪、坐标映射环节即可。
核心实现逻辑
- 逐帧读取网络摄像头画面,先将完整帧输入model1推理,拿到原帧尺度下model1输出的所有检测框坐标(x1,y1,x2,y2,左上角+右下角绝对像素值)、置信度、类别信息。
- 遍历model1输出的符合筛选要求的边界框,按坐标从原帧中裁剪出对应ROI(感兴趣区域)子图,裁剪前要做坐标边界截断,避免坐标超出画面宽高引发报错。
- 将裁剪得到的ROI子图输入model2推理,此时model2输出的检测框坐标是相对于ROI子图左上角的相对值,需要做坐标偏移转换:所有检测框的x坐标累加对应ROI的左上角x1值、y坐标累加对应ROI的左上角y1值,即可得到原帧尺度下的绝对坐标。
- 将model1的检测结果、坐标转换后的model2检测结果统一绘制到原帧上,可用不同颜色区分两个模型的检测框,最终输出到显示窗口即可。
可直接参考的实现代码
import torch import cv2 # 加载本地训练好的两个YOLOv5模型 model1 = torch.hub.load('ultralytics/yolov5', 'custom', path='model1.pt') model2 = torch.hub.load('ultralytics/yolov5', 'custom', path='model2.pt') # 按需设置两个模型的置信度阈值 model1.conf = 0.5 model2.conf = 0.4 # 接入视频流,0为本地默认摄像头,替换为rtsp地址即可接入网络摄像头 cap = cv2.VideoCapture(0) frame_w = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)) frame_h = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT)) while cap.isOpened(): ret, frame = cap.read() if not ret: break # 第一级:model1检测全帧 res1 = model1(frame) dets1 = res1.xyxy[0].cpu().numpy() dets2 = [] # 遍历model1检测框,裁剪ROI送入model2 for det in dets1: x1, y1, x2, y2, conf1, cls1 = det # 坐标越界截断 x1, y1 = max(0, int(x1)), max(0, int(y1)) x2, y2 = min(frame_w, int(x2)), min(frame_h, int(y2)) # 裁剪ROI区域 roi = frame[y1:y2, x1:x2] if roi.size == 0: continue # 第二级:model2检测ROI区域 res2 = model2(roi) roi_dets = res2.xyxy[0].cpu().numpy() # 坐标转换:将ROI内相对坐标映射回原帧绝对坐标 for r_det in roi_dets: rx1, ry1, rx2, ry2, conf2, cls2 = r_det dets2.append([ x1 + rx1, y1 + ry1, x1 + rx2, y1 + ry2, conf2, cls2 ]) # 绘制结果:model1检测框用蓝色,model2检测框用红色 for det in dets1: x1, y1, x2, y2, conf, cls = det x1, y1, x2, y2 = int(x1), int(y1), int(x2), int(y2) cv2.rectangle(frame, (x1, y1), (x2, y2), (255, 0, 0), 2) cv2.putText(frame, f"{model1.names[int(cls)]} {conf:.2f}", (x1, y1-10), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (255, 0, 0), 2) for det in dets2: x1, y1, x2, y2, conf, cls = det x1, y1, x2, y2 = int(x1), int(y1), int(x2), int(y2) cv2.rectangle(frame, (x1, y1), (x2, y2), (0, 0, 255), 2) cv2.putText(frame, f"{model2.names[int(cls)]} {conf:.2f}", (x1, y1-10), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 0, 255), 2) cv2.imshow('two-stage detection', frame) # 按q键退出 if cv2.waitKey(1) & 0xFF == ord('q'): break cap.release() cv2.destroyAllWindows()
优化提示
- 如果model2仅需要处理model1输出的特定类别目标,可以在遍历model1检测结果时增加类别判断,仅裁剪符合类别要求的框区域,减少无效计算。
- 如果对推理速度要求高,可以把同帧下所有裁剪出的ROI攒成一个batch输入model2做批量推理,相比逐个ROI推理能明显降低延迟。
- 坐标转换时不要遗漏ROI左上角的偏移值,否则model2的检测框会错位到画面左上角。
内容的提问来源于stack exchange,提问作者andy wong
相关产品推荐
相关产品推荐

