Pygame如何从已加载的视频中提取指定帧并解决相关报错
解决方案
报错原因
你尝试使用video_image[15].tobytes()获取第15帧的写法完全错误:
video_image是单次调用video.read()返回的单帧图像,是维度为(高度, 宽度, 3)的numpy数组,video_image[15]的含义是取出这一帧的第15行像素,得到的数组维度为(宽度, 3),不是完整的帧数据- 传入
pygame.image.frombuffer的第二个参数要求是(宽度, 高度)的二元组,你传入的单行像素的维度不符合要求,因此抛出类型错误 - 要读取指定序号的帧,需要通过OpenCV的
VideoCapture属性设置接口调整读取位置,不能直接索引单帧对象
点击鼠标获取当前帧的实现
只需要在原有代码的事件循环中新增鼠标点击事件的监听逻辑,触发时直接存储当前的video_image即可,你可以选择将其保存为本地图片,或者转成Pygame表面对象留存。
完整修改后代码
import pygame import cv2 video = cv2.VideoCapture("video.mp4") success, video_image = video.read() if not success: print("视频读取失败") exit() fps = video.get(cv2.CAP_PROP_FPS) # 总帧数可用于后续帧跳转的边界判断 total_frames = video.get(cv2.CAP_PROP_FRAME_COUNT) window = pygame.display.set_mode(video_image.shape[1::-1]) clock = pygame.time.Clock() run = success while run: clock.tick(fps) for event in pygame.event.get(): if event.type == pygame.QUIT: run = False # 新增鼠标点击事件处理 if event.type == pygame.MOUSEBUTTONDOWN: # 点击时保存当前帧到本地,命名包含当前帧序号 current_frame_num = int(video.get(cv2.CAP_PROP_POS_FRAMES)) save_path = f"frame_{current_frame_num}.jpg" cv2.imwrite(save_path, video_image) print(f"已保存当前帧到{save_path}") success, video_image = video.read() if success: video_surf = pygame.image.frombuffer( video_image.tobytes(), video_image.shape[1::-1], "BGR") else: run = False window.blit(video_surf, (0, 0)) pygame.display.flip() # 读取指定帧的示例:读取第15帧 # 注意帧序号从0开始计数,第15帧对应序号为14 video.set(cv2.CAP_PROP_POS_FRAMES, 14) success, frame_15 = video.read() if success: cv2.imwrite("frame_15.jpg", frame_15) # 转成Pygame表面的标准写法 frame_15_surf = pygame.image.frombuffer(frame_15.tobytes(), frame_15.shape[1::-1], "BGR") pygame.quit() exit()
内容的提问来源于stack exchange,提问作者Ivan Yosifov
相关产品推荐
相关产品推荐

