CNN(AlexNet)+LSTM视频预测模型帧处理与输入适配问题咨询
报错根因
你的代码和模型输入要求存在4个核心不匹配问题:
- 模型要求输入为连续10帧、尺寸299×299、3通道RGB的序列,你当前代码是单帧读取就直接输入预测,没有凑够10帧的序列
- 你调用了
cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)把3通道彩色帧转成了单通道灰度图,不符合3通道的输入要求 - 帧缩放用的是等比缩20%的逻辑,输出尺寸不固定,没有统一调整到模型要求的299×299
- 输入到
model.predict的张量没有补齐批次维度,维度顺序也完全不匹配模型要求
调整逻辑
- 维护一个长度固定为10的帧队列,每读取到新帧就处理后加入队列,队列满了之后再输入模型做预测,实现滑动窗口式的逐帧检测
- 取消灰度转换步骤,直接将OpenCV默认读入的BGR格式帧转成RGB(和模型训练的输入格式对齐)
- 固定把所有帧resize到299×299,不用等比缩放,保证任意输入视频的帧尺寸都符合要求
- 把队列里的10帧堆叠后,在最前面加一个批次维度,再输入模型预测
修改后可运行代码
import cv2 import numpy as np # 初始化固定长度为10的帧缓存队列 frame_buffer = [] # 模型要求的输入尺寸 INPUT_SIZE = (299, 299) # 单次预测需要的帧数 SEQ_LEN = 10 while vid.isOpened(): ret, frame = vid.read() if not ret: break # 1. 帧预处理:统一缩放到299×299,BGR转RGB processed_frame = cv2.resize(frame, INPUT_SIZE, interpolation=cv2.INTER_AREA) processed_frame = cv2.cvtColor(processed_frame, cv2.COLOR_BGR2RGB) # 可选:如果模型训练时做了归一化,这里要加对应的逻辑,比如 processed_frame = processed_frame / 255.0 # 2. 帧加入缓存队列 frame_buffer.append(processed_frame) # 队列长度超过要求就弹出最早的帧,维持滑动窗口 if len(frame_buffer) > SEQ_LEN: frame_buffer.pop(0) # 3. 队列凑够10帧才做预测 texto = "" if len(frame_buffer) == SEQ_LEN: # 堆叠成模型要求的输入格式:(1, 10, 299, 299, 3) 1是批次维度 model_input = np.expand_dims(np.array(frame_buffer), axis=0) # 预测 pred = model.predict(model_input, verbose=0) # 这里根据你模型的输出逻辑调整取值即可,原代码中pred是预测结果数组不是函数,不需要调用pred(frame) texto = str(pred[0]) # 4. 结果绘制到原始帧展示 frame = cv2.putText(frame, texto, (0,130), cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 255, 255), 3) cv2.imshow('Video', frame) if cv2.waitKey(25) & 0xFF == ord('q'): break vid.release() cv2.destroyAllWindows()
注意事项
- 如果你的模型训练时对输入帧做了归一化(比如除以255、减均值除标准差),需要在预处理部分加上对应的逻辑,否则预测结果会不准
- 上面的代码是滑动窗口预测,也就是每新来一帧就会用最新的10帧做一次预测,符合逐帧检测的需求
- 如果你不需要滑动窗口,而是每10帧预测一次,就把
len(frame_buffer) > SEQ_LEN的判断改成len(frame_buffer) == SEQ_LEN时预测后清空队列即可
内容的提问来源于stack exchange,提问作者JuniorPython
相关产品推荐
相关产品推荐

