YOLOv8+OpenCV黄红区域目标检测判断逻辑异常问题排查
问题排查与解决方案
核心问题分析
- 坐标偏移错误:你对帧做了裁剪
cropped_frame = resized_frame[x_line1:, y_line:],YOLO返回的检测框坐标是基于这个裁剪后图像的局部坐标系,而非原resized_frame的全局坐标系。直接用box[1](裁剪图的y坐标)和原图像的x_line2(全局y坐标)比较,数值永远不匹配——裁剪图的y=0对应原图的y=x_line1=200,所以实际全局y坐标应该是box[1] + x_line1。 - 变量命名混淆:
x_line1、x_line2实际是水平线的y轴坐标(OpenCV中水平线的y值固定),命名错误容易导致逻辑判断时的坐标混淆。
修正后的代码
import cv2 import torch import numpy as np from ultralytics import YOLO if torch.cuda.is_available(): device = torch.device('cuda') print('Using device:', torch.cuda.get_device_name(torch.cuda.current_device())) else: device = torch.device('cpu') print('Using device:', device) video_path ="rtsp://192.168.1.83/live/0/MAIN" cap = cv2.VideoCapture(video_path) model = YOLO('yolov8n.pt') # 修正变量命名:明确水平线对应y轴坐标,竖直线对应x轴坐标 y_line1 = 200 # 第一条水平线(黄区上边界) y_line2 = 500 # 第二条水平线(红区上边界) x_vertical_line = 350 # 竖直线的x坐标 frame_count = 0 while cap.isOpened(): success, frame = cap.read() width = int(cap.get(3)) height = int(cap.get(4)) if success: resized_frame = cv2.resize(frame, (1280, 720), interpolation=cv2.INTER_LINEAR) # 绘制线条,使用修正后的变量名 cv2.line(resized_frame, (0, y_line1), (1280, y_line1), (255, 0, 0), 10) cv2.line(resized_frame, (0, y_line2), (1280, y_line2), (255, 0, 0), 10) cv2.line(resized_frame, (x_vertical_line, 0), (x_vertical_line, 720), (255, 0, 0), 10) # 裁剪帧:y_line1以下,x_vertical_line右侧的区域 cropped_frame = resized_frame[y_line1:, x_vertical_line:] results = model(cropped_frame, conf=0.1) annotated_cropped_frame = results[0].plot() annotated_frame = resized_frame.copy() annotated_frame[y_line1:, x_vertical_line:] = annotated_cropped_frame cv2.imshow("YOLOv8 Inference", annotated_frame) if cv2.waitKey(1) & 0xFF == ord("q"): break num_objects = len(results[0].boxes) if num_objects >= 9: cv2.imwrite("frame_{}.jpg".format(frame_count), annotated_frame) print(f"There are {num_objects} people in the frame") boxes = results[0].boxes.data for box in boxes: # 计算目标在原resized_frame中的全局y坐标:裁剪图的y坐标 + 裁剪偏移量y_line1 global_y = box[1] + y_line1 if global_y > y_line2: print("Object is in red zone") elif global_y > y_line1: print("Object is in yellow zone") else: # 可选:处理目标在第一条线以上的情况 print("Object is in zone above first line") frame_count += 1 else: break cap.release() cv2.destroyAllWindows()
关键修正点
- 变量命名优化:将
x_line1/x_line2改为y_line1/y_line2,y_line改为x_vertical_line,明确坐标含义,避免混淆。 - 坐标偏移修正:计算目标在全局坐标系中的y坐标
global_y = box[1] + y_line1,确保和绘制的水平线坐标在同一系统下比较。 - 完善判断逻辑:补充了目标在第一条线以上的情况,让逻辑更完整。
内容的提问来源于stack exchange,提问作者Arnav86
相关产品推荐
相关产品推荐

