Keras+OpenCV输入维度不匹配报错:预期4维输入却得到3维
嘿,我帮你排查了这个问题,核心原因其实很明确,咱们一步步来解决:
问题根源
你碰到的ValueError是因为Keras的predict方法要求输入必须是批量数据(4维张量:[batch_size, 高度, 宽度, 通道数]),但你传进去的是单张图片的3维张量([48,48,3])。虽然你打印的roi.shape显示是(48,48,3)——这是单张图片的正确形状,但模型需要的是带batch维度的输入,所以才会提示“预期最小维度为4,实际得到维度3”。
另外,你的模型定义代码还有个小语法错误:第一个Conv2D层末尾少了个闭合括号,这会导致模型构建失败,得先把这个修好。
分步解决办法
1. 先修复模型的语法错误
修改你的Keras模型代码,给第一个Conv2D层补上闭合括号:
model = Sequential([ Conv2D(filters=32,kernel_size=(3,3), activation='relu', padding = 'same', input_shape=(48, 48, 3)), # 补上缺失的闭合括号 MaxPool2D(pool_size=(2, 2), strides=2), Conv2D(filters=64, kernel_size=(3, 3), activation='relu', padding = 'same'), MaxPool2D(pool_size=(2, 2), strides=2), Flatten(), Dense(units=2, activation='softmax'), ])
2. 给预测输入添加Batch维度
在trueoruntruemodel类的predict_true方法里,用np.expand_dims()给输入图片添上batch维度,把形状从(48,48,3)转成(1,48,48,3)——这就完全符合模型的输入要求了:
def predict_true(self, img): # 添加batch维度:单张图片转为批量大小为1的输入 img_with_batch = np.expand_dims(img, axis=0) self.preds = self.loaded_model.predict(img_with_batch) return trueoruntruemodel.options[np.argmax(self.preds)]
3. (可选但关键)统一图片色彩格式
OpenCV默认采集的图片是BGR格式,但如果你的模型训练时用的是RGB格式(比如用PIL或Keras内置工具加载训练数据),那预测时必须转换格式,否则会严重影响准确率:
在摄像头采集的get_frame方法里添加色彩空间转换:
def get_frame(self): _, fr = self.video.read() print(fr.shape) roi = cv2.resize(fr, (48, 48)) # 将OpenCV的BGR格式转为RGB格式(匹配训练数据的格式) roi_rgb = cv2.cvtColor(roi, cv2.COLOR_BGR2RGB) print(roi_rgb.shape) # 输出仍为(48,48,3),仅通道顺序调整 pred = model.predict_true(roi_rgb) # 传入转换后的图片 # 注意:你原代码中x,y未定义,这里示例设为(50,50) cv2.putText(fr, pred, (50,50), font, 1, (46, 46, 0), 2) _, jpeg = cv2.imencode('.jpg', fr) return jpeg.tobytes()
另外,你代码里cv2.putText的x,y变量未定义,必须补充具体坐标值,不然会触发变量未定义的错误,上面的代码给了示例值。
为啥设置batch_input_shape没用?
你尝试设置batch_input_shape=(None,48,48,3)其实是正确的模型输入定义,但问题出在预测时没有传入符合该形状的输入。batch_input_shape中的None表示batch大小可变,但输入必须至少有4个维度,而你传入的是3维单张图片,所以依然不兼容。
内容的提问来源于stack exchange,提问作者Stackaccount1

