TFLite模型在Android与Kivy应用中输出不一致致崩溃
Kivy国际象棋检测APP安卓端推理崩溃问题
问题现象
开发基于Kivy的国际象棋棋子检测APP时,将YOLOv8模型转为TFLite格式后,PC端运行get_positions推理方法完全正常,但打包成Android APK后,应用因模型输出处理异常崩溃。
具体错误为:ValueError: not enough values to unpack (expected 4, got 1),根源是PC端cv2.dnn.NMSBoxes返回一维数组格式的indices,而Android端返回二维数组,导致循环中x_center, y_center, width, height = boxes_xywh[i]执行时索引错误。
推理方法代码
def get_positions(model_path, img_name): print("Loading model...") interpreter = Interpreter(model_path=model_path) interpreter.allocate_tensors() input_details = interpreter.get_input_details() output_details = interpreter.get_output_details() print("Input details:", input_details) print("Output details:", output_details) print("Loading image...") image = cv2.imread(img_name) if image is None: raise ValueError(f"Could not load the image from {img_name}") print("Original image dimensions:", image.shape) image_height = input_details[0]['shape'][1] image_width = input_details[0]['shape'][2] resized_image = cv2.resize(image, (image_width, image_height)) input_image = np.array(resized_image, dtype=np.float32) / 255.0 input_image = input_image[np.newaxis, :] print("Resized image dimensions:", input_image.shape) interpreter.set_tensor(input_details[0]['index'], input_image) interpreter.invoke() output = interpreter.get_tensor(output_details[0]['index']) output = output[0] output = output.T print("Model output:", output) boxes_xywh = output[..., :4] scores = np.max(output[..., 4:], axis=1) print("Scores:", scores) classes = np.argmax(output[..., 4:], axis=1) indices = cv2.dnn.NMSBoxes(boxes_xywh.tolist(), scores.tolist(), confidence_threshold, iou_threshold) print("Indices after NMS:", indices) results = [] for i in indices: if scores[i] >= confidence_threshold: x_center, y_center, width, height = boxes_xywh[i] x_center, width = x_center * image_width, width * image_width y_center, height = y_center * image_height, height * image_height x_center /= image_width y_center /= image_height width /= image_width height /= image_height result = { 'class_id': classes[i], 'class_name': CLASSES[classes[i]], 'x_center': x_center, 'y_center': y_center, 'width': width, 'height': height, 'confidence': scores[i] } print("Result:", result) results.append(result) return results
解决方案
问题核心是cv2.dnn.NMSBoxes在不同平台返回的indices格式不统一,需要统一处理为一维数组后再遍历:
修改循环前的indices处理逻辑,将二维数组扁平化:
# 统一处理indices格式,兼容一维/二维返回值 indices = cv2.dnn.NMSBoxes(boxes_xywh.tolist(), scores.tolist(), confidence_threshold, iou_threshold) # 将indices转为一维数组 indices = indices.flatten() if len(indices.shape) > 1 else indices print("Indices after NMS (flattened):", indices) results = [] for i in indices: # 后续逻辑保持不变 if scores[i] >= confidence_threshold: x_center, y_center, width, height = boxes_xywh[i] # ... 剩余代码
也可以用numpy的squeeze方法去除多余维度:
indices = np.squeeze(indices)
这样无论PC还是Android端返回的indices是一维还是二维,都会被转为一维数组,循环中boxes_xywh[i]就能正确获取到4个值,避免解包错误。
内容的提问来源于stack exchange,提问作者Juan Rafael Iniesta
相关产品推荐
相关产品推荐

