CameraXAdvanced替换自定义模型后遇TensorFlowLite形状不匹配问题求助
第一个错误:输入张量尺寸/数据类型不匹配
错误信息:
java.lang.IllegalArgumentException: Cannot copy to a TensorFlowLite tensor (serving_default_conv2d_input:0) with 480000 bytes from a Java Buffer with 120000
原因
训练时模型输入是300x300x3的float32类型(已做1./255归一化),但CameraXAdvanced默认的图像预处理逻辑是针对原目标检测模型的,尺寸、数据类型或归一化方式不匹配。
解决步骤
调整输入图像尺寸与预处理逻辑
在CameraActivity.kt中修改图像处理器的配置,对齐训练时的参数:val imageProcessor = ImageProcessor.Builder() .add(ResizeOp(300, 300, ResizeOp.ResizeMethod.BILINEAR)) // 匹配训练时的IMAGE_SIZE .add(NormalizeOp(0f, 255f)) // 对应训练时的1./255归一化 .add(CastOp(DataType.FLOAT32)) // 转换为模型所需的float32类型 .build()确认通道顺序
确保输入图像为RGB通道顺序(训练时ImageDataGenerator默认使用RGB),若CameraX输出为YUV/BGR格式,需添加对应转换操作:// 示例:若为BGR转RGB,添加对应转换Op .add(ColorSpaceTransformOp(...)) // 根据实际图像格式调整转换参数
第二个错误:输出张量解析逻辑不匹配
错误信息:
java.lang.IllegalArgumentException: Cannot copy from a TensorFlowLite tensor (StatefulPartitionedCall:0) with shape [1, 11] to a Java object with shape [1, 11, 4]
原因
原示例是目标检测模型,输出包含检测框坐标(4个参数)和分类结果;而你的自定义模型是纯图像分类,输出仅为[1,11](11个类别的概率),原代码的输出解析逻辑完全不匹配。
解决步骤
修改输出缓冲区定义
在CameraActivity.kt中替换原目标检测的输出数组,改为分类模型的尺寸:// 替换原目标检测输出数组 // val outputBuffer = Array(1) { Array(11) { FloatArray(4) } } // 改为分类模型的输出缓冲区 val outputBuffer = Array(1) { FloatArray(11) }调整推理调用参数
调用Interpreter.run时传入正确的输出缓冲区:interpreter.run(inputBuffer, outputBuffer)重写分类结果解析逻辑
删除原检测框解析代码,直接处理分类概率,获取置信度最高的类别:val probabilities = outputBuffer[0] val maxIndex = probabilities.indices.maxByOrNull { probabilities[it] } ?: 0 val predictedClass = labels[maxIndex] // labels为从my_model.txt加载的类别列表 val confidence = probabilities[maxIndex] // 后续可将predictedClass和confidence展示在UI上清理冗余代码
删除原示例中与目标检测相关的逻辑(如检测框绘制、边界框计算等),仅保留图像分类所需的代码模块。
内容的提问来源于stack exchange,提问作者AndrWa

