如何在视频帧上叠加Quiver图并实现可视化?
视频帧叠加Quiver图的错误修复与实现
错误原因分析
- 核心错误:使用
plt.plot()绘制图像数组。plt.plot()是折线图接口,无法处理3通道图像的高维数组(形状(3,280,300)),导致维度不匹配报错。 - 辅助问题:
- 像素遍历效率极低,嵌套循环处理单像素会拖慢运行速度
- 错误移动图像通道轴,不符合matplotlib图像显示的格式要求
- 未处理视频读取结束的边界情况,可能导致空帧报错
- 未提前创建保存目录,保存图像时会抛出路径不存在错误
修复后的完整代码
import numpy as np import cv2 import os import matplotlib.pyplot as plt # 创建保存目录 os.makedirs('QUIVER', exist_ok=True) cap = cv2.VideoCapture('Video.mp4') lower = np.array([22, 93, 0]) upper = np.array([45, 255, 255]) while cap.isOpened(): ret, frame = cap.read() # 读取到空帧时退出循环 if not ret: break frame_id = int(cap.get(cv2.CAP_PROP_POS_FRAMES)) # 裁剪参数 size_x_l, size_x_u = 70, 350 size_y_l, size_y_u = 130, 430 frame_cropped = frame[size_x_l:size_x_u, size_y_l:size_y_u] # 用cv2.inRange替代嵌套循环,快速提取符合颜色范围的区域 mask = cv2.inRange(frame_cropped, lower, upper) # 将符合条件的区域转为灰度,其余为黑 yellow = cv2.cvtColor(mask, cv2.COLOR_GRAY2BGR) gray = cv2.cvtColor(frame_cropped, cv2.COLOR_BGR2GRAY) yellow[mask > 0] = cv2.cvtColor(gray[mask > 0][:, None], cv2.COLOR_GRAY2BGR) # 设置保存路径 f_name = os.path.join('QUIVER', f'{frame_id}.jpg') # 创建画布,叠加图像和Quiver图 fig, ax = plt.subplots(figsize=(8, 6)) # 将BGR转为RGB,适配matplotlib显示 rgb_yellow = cv2.cvtColor(yellow, cv2.COLOR_BGR2RGB) ax.imshow(rgb_yellow) # 绘制Quiver图:示例为单个箭头,如需多个可生成网格坐标 # 单个箭头示例 X, Y = 70, 70 U, V = -5, 5 ax.quiver(X, Y, U, V, color='r', width=.01, linewidth=1) # 可选:绘制网格状箭头(取消注释启用) # X, Y = np.meshgrid(np.arange(50, 250, 50), np.arange(50, 300, 50)) # U = np.ones_like(X) * -2 # V = np.ones_like(Y) * 2 # ax.quiver(X, Y, U, V, color='r', width=.005, linewidth=0.5) # 关闭坐标轴(可选) ax.axis('off') # 保存画布,去掉多余空白 plt.savefig(f_name, bbox_inches='tight', pad_inches=0) plt.close(fig) # 关闭画布释放内存 cap.release()
关键修改说明
- 颜色区域提取优化:用
cv2.inRange()替代三层嵌套循环,直接生成颜色掩码,处理速度提升数十倍 - 图像显示修正:使用
ax.imshow()替代plt.plot(),并保持图像的(H,W,C)格式,无需移动通道轴 - 边界逻辑完善:添加
if not ret: break,处理视频读取完毕的情况;提前创建保存目录避免路径错误 - Quiver图灵活配置:支持单个箭头或网格状箭头,可根据需求调整坐标和向量参数
- 内存优化:每次循环后关闭画布
plt.close(fig),避免内存泄漏
内容的提问来源于stack exchange,提问作者Aleph
相关产品推荐
相关产品推荐

