在Colab中用加载的TensorFlow/Keras CNN模型实现摄像头预测遇形状问题
解决模型输入不匹配的问题
为啥会报错?
你的模型训练时用的是224×224的RGB彩色图,所以它要求输入得是**(批量大小, 224, 224, 3)**这种格式。但你现在传的gray是单通道的灰度图,形状是(32,640)——尺寸不对、通道数不对,还没加批量维度,模型自然不认。
怎么改?
直接按下面的步骤调整你的代码,重点是在预测前把摄像头帧处理成模型要的样子:
1. 核心预处理步骤
在调用model.predict()之前,必须对摄像头帧做这几步:
- 把OpenCV默认的BGR格式转成RGB(和训练时的输入格式对齐)
- 把帧的尺寸缩放到224×224
- 给数据加个批量维度(因为
model.predict()只接受批量数据输入) - 做和训练时一样的归一化(比如除以255,把像素值弄到0-1之间)
2. 可直接用的代码片段
import cv2 import numpy as np from tensorflow.keras.models import load_model from google.colab.patches import cv2_imshow from IPython.display import display, Javascript from google.colab.output import eval_js from base64 import b64decode # 加载你的模型 model = load_model('你的模型文件路径.h5') # Colab摄像头调用工具函数 def get_camera_frame(quality=0.8): js = Javascript(''' async function captureFrame(quality) { const video = document.createElement('video'); video.style.display = 'none'; const stream = await navigator.mediaDevices.getUserMedia({video: true}); document.body.appendChild(video); video.srcObject = stream; await video.play(); const canvas = document.createElement('canvas'); canvas.width = video.videoWidth; canvas.height = video.videoHeight; canvas.getContext('2d').drawImage(video, 0, 0); stream.getVideoTracks()[0].stop(); video.remove(); return canvas.toDataURL('image/jpeg', quality); } ''') display(js) data = eval_js('captureFrame({})'.format(quality)) binary = b64decode(data.split(',')[1]) # 把二进制数据转成OpenCV能读的格式 np_arr = np.frombuffer(binary, np.uint8) frame = cv2.imdecode(np_arr, cv2.IMREAD_COLOR) return frame # 实时预测循环 while True: # 获取摄像头帧 frame = get_camera_frame() # 关键:预处理帧,匹配模型输入 # 转成RGB(训练时用RGB的话) rgb_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB) # 缩放到224×224 resized = cv2.resize(rgb_frame, (224, 224)) # 加批量维度:(224,224,3) → (1,224,224,3) input_data = np.expand_dims(resized, axis=0) # 归一化(和训练时一致,比如训练时除以255) input_data = input_data / 255.0 # 执行预测 predictions = model.predict(input_data) # 取概率最高的类别(分类任务的话) predicted_class = np.argmax(predictions, axis=1)[0] # 显示结果 print(f"预测类别:{predicted_class}") cv2_imshow(frame) # 手动中断循环即可退出(Colab里没法用键盘按键退出,直接点停止按钮)
3. 要注意的细节
- 预处理必须和训练时完全一致:比如训练时如果用了
ImageDataGenerator的rescale=1/255,这里就必须做同样的归一化;如果训练时是灰度图,那就要把帧转成灰度再扩通道到(1,224,224,1)——但根据你的错误提示,模型是3通道输入,所以优先用RGB。 - 你提到的
32是摄像头当前帧的高度,不用手动改,用cv2.resize()把它缩到224就行,代码里已经处理了。
内容的提问来源于stack exchange,提问作者NoneStopCoding
相关产品推荐
相关产品推荐

