TensorFlow摄像头推理报错:tf.function输入绑定类型不匹配
问题分析与解决方案
核心问题是摄像头捕获的输入张量未匹配模型要求的格式:模型期望(1, None, None, 3)的tf.uint8张量,但实际输入是含NaN的(1,)形状tf.float32张量。由于图片推理正常,说明模型本身无问题,问题出在摄像头帧的读取与预处理环节。
具体排查与修复步骤
1. 检查摄像头帧读取有效性
- 捕获帧后立即校验是否为空:摄像头初始化或异常时可能返回空帧,直接处理会生成NaN
cap = cv2.VideoCapture(cam_index) ret, frame = cap.read() if not ret or frame is None: continue # 跳过无效帧,避免后续错误 - 强制转换帧类型与形状:将读取到的帧转为模型期望的
uint8,并添加batch维度# 先转成uint8(摄像头帧一般是numpy数组,先转tensor再强制类型) frame_tensor = tf.convert_to_tensor(frame, dtype=tf.uint8) # 添加batch轴,匹配输入形状(1, H, W, 3) input_tensor = tf.expand_dims(frame_tensor, axis=0)
2. 对齐图片与摄像头的预处理流程
- 完全复用图片推理的预处理代码:比如图片推理时的resize、色彩空间转换、归一化逻辑,原封不动套用到摄像头帧上
# 假设图片推理的预处理函数是preprocess_img def preprocess_img(img): img = tf.image.resize(img, (224, 224)) # 示例尺寸,按你的训练参数调整 img = tf.cast(img, tf.uint8) return tf.expand_dims(img, 0) # 摄像头帧直接用这个函数处理 input_tensor = preprocess_img(frame) - 禁止提前将帧转为float32:模型期望uint8输入,不要在预处理前做不必要的类型转换,避免引入NaN
3. 修复摄像头捕获的底层问题
- 检查帧通道数:部分摄像头可能返回灰度图(单通道),需转为3通道RGB
if frame.ndim == 2: # 灰度图 frame = cv2.cvtColor(frame, cv2.COLOR_GRAY2RGB) - 验证摄像头原始输出:单独编写测试代码,确认摄像头能输出正常图像
cap = cv2.VideoCapture(cam_index) while True: ret, frame = cap.read() if ret: cv2.imshow("Cam Test", frame) if cv2.waitKey(1) & 0xFF == ord('q'): break cap.release() cv2.destroyAllWindows()
4. 新增NaN校验逻辑
- 在推理前加入断言,快速定位无效帧
tf.debugging.assert_all_finite(input_tensor, "Input contains NaN/Infinity") # 之后再执行推理 predictions = model(input_tensor)
内容的提问来源于stack exchange,提问作者Beetran Dahiya
相关产品推荐
相关产品推荐

