如何用OpenCV读取Pygame窗口画面并叠加目标检测标注框
实现方案
核心思路
不需要通过cv2.VideoCapture()捕获系统窗口,直接从pygame的Surface对象中提取像素数据,转换为cv2兼容的格式后送入目标检测逻辑,最后将检测得到的框坐标直接用pygame原生接口绘制到原窗口即可,比系统级窗口捕获效率更高、兼容性更好。
前置依赖
需要安装以下库:
pip install pygame opencv-python numpy
具体实现步骤
- 完成原有pygame窗口的绘制逻辑后,从窗口Surface中提取3通道像素数组
- 将pygame返回的RGB格式、维度为(宽,高,3)的数组,转换为cv2要求的BGR格式、维度为(高,宽,3)的数组
- 转换后的数组和
cv2.VideoCapture()读取的本地视频帧格式完全一致,直接送入你原有目标检测逻辑即可 - 得到检测结果的框坐标后,直接用
pygame.draw.rect()绘制到原pygame窗口,实现叠加效果;也可以将框绘制到cv2格式的帧上,通过cv2.imshow()打开新窗口展示
可运行示例代码
import pygame import cv2 import numpy as np # 初始化pygame窗口 pygame.init() screen_width, screen_height = 800, 600 screen = pygame.display.set_mode((screen_width, screen_height)) clock = pygame.time.Clock() fps = 30 # 目标检测函数:替换为你自己的检测逻辑即可 def object_detection(cv2_frame): # 输入的cv2_frame和你之前读取本地视频得到的帧格式完全一致 # 此处返回检测到的所有框,格式为[(x1, y1, width, height)] # 示例返回模拟的检测框 return [(100, 150, 200, 150)] running = True while running: # 处理窗口事件 for event in pygame.event.get(): if event.type == pygame.QUIT: running = False # -------------------------- # 此处替换为你原有pygame的绘制逻辑 screen.fill((255, 255, 255)) pygame.draw.circle(screen, (0, 0, 255), (400, 300), 50) # -------------------------- # 1. 从pygame窗口提取像素,转cv2兼容格式 pygame_pixels = pygame.surfarray.array3d(screen) # 调整维度+转换颜色通道 cv2_frame = cv2.cvtColor(np.transpose(pygame_pixels, (1, 0, 2)), cv2.COLOR_RGB2BGR) # 2. 送入目标检测 detect_boxes = object_detection(cv2_frame) # 3. 叠加检测框到原pygame窗口 for (x, y, w, h) in detect_boxes: pygame.draw.rect(screen, (255, 0, 0), (x, y, w, h), 2) # 可选:在新cv2窗口展示检测结果 # for (x,y,w,h) in detect_boxes: # cv2.rectangle(cv2_frame, (x,y), (x+w, y+h), (0,0,255), 2) # cv2.imshow("检测结果", cv2_frame) # cv2.waitKey(1) # 刷新pygame窗口 pygame.display.flip() clock.tick(fps) pygame.quit() cv2.destroyAllWindows()
注意事项
- pygame和cv2的坐标原点都在左上角,检测得到的框坐标不需要额外转换可以直接使用
- 如果检测模型对输入尺寸有要求,直接对转换后的
cv2_frame做resize处理即可,和原有处理本地视频帧的逻辑一致 - 高分辨率场景下如果出现卡顿,可以先将
cv2_frame降采样后再送入检测,绘制框时将坐标按比例缩放回原窗口尺寸即可
内容的提问来源于stack exchange,提问作者Cristina
相关产品推荐
相关产品推荐

