Unity中使用TensorFlow Lite模型报错求助:GetOutputTensor无法访问等问题
Unity中TensorFlow Lite分类模型调用错误修复
问题背景
有一个以图像为输入的TensorFlow Lite分类模型,需要在Unity项目中使用。使用ChatGPT生成的代码后出现两个编译错误,此前用.h5模型结合Python在C#中可运行,但导出APK后失效,因此改用TensorFlow Lite方案。
错误信息
Assets\Samples\Detection\Scripts\PythonBridge.cs(72,9): error CS0246: 找不到类型或命名空间名称‘Tensor’(是否缺少using指令或程序集引用?)Assets\Samples\Detection\Scripts\PythonBridge.cs(72,43): error CS0122: ‘Interpreter.GetOutputTensor(int)’因保护级别无法访问
原代码
using UnityEngine; using TensorFlowLite; using System.IO; using System.Collections.Generic; public class ObjectDetection : MonoBehaviour { [SerializeField] [FilePopup("*.tflite")] public string modelPath = "model.tflite"; [SerializeField] private TextAsset labelFile; [SerializeField] private Texture2D inputImage; private Interpreter interpreter; private List<string> labels; private const int IMAGE_SIZE = 224; private const int CHANNELS = 3; private void Start() { LoadModel(); LoadLabels(); PreprocessImage(); RunInference(); } private void LoadModel() { interpreter = new Interpreter(File.ReadAllBytes(modelPath)); } private void LoadLabels() { labels = new List<string>(); using (StringReader reader = new StringReader(labelFile.text)) { string line; while ((line = reader.ReadLine()) != null) { labels.Add(line.Trim()); } } } private void PreprocessImage() { Texture2D resizedImage = ResizeImage(inputImage, IMAGE_SIZE, IMAGE_SIZE); Color32[] pixels = resizedImage.GetPixels32(); float[] imgArray = new float[IMAGE_SIZE * IMAGE_SIZE * CHANNELS]; for (int i = 0; i < pixels.Length; i++) { imgArray[i * 3] = pixels[i].r / 255.0f; imgArray[i * 3 + 1] = pixels[i].g / 255.0f; imgArray[i * 3 + 2] = pixels[i].b / 255.0f; } interpreter.SetInputTensorData(0, imgArray); } private void RunInference() { interpreter.Invoke(); // Retrieve output and process predictions Tensor outputTensor = interpreter.GetOutputTensor(0); float[] results = outputTensor.Data<float>(); // Find class with highest probability int maxIndex = 0; float maxProbability = 0f; for (int i = 0; i < results.Length; i++) { if (results[i] > maxProbability) { maxProbability = results[i]; maxIndex = i; } } string predictedLabel = labels[maxIndex]; Debug.Log("Predicted object: " + predictedLabel); } private Texture2D ResizeImage(Texture2D source, int width, int height) { RenderTexture rt = RenderTexture.GetTemporary(width, height, 24); RenderTexture.active = rt; Graphics.Blit(source, rt); Texture2D result = new Texture2D(width, height); result.ReadPixels(new Rect(0, 0, width, height), 0, 0); result.Apply(); RenderTexture.active = null; RenderTexture.ReleaseTemporary(rt); return result; } }
错误原因及修复方案
错误1:找不到Tensor类型
TensorFlow Lite for Unity的官方API中,并没有公开的Tensor类供直接使用,ChatGPT生成的代码使用了过时或不存在的API。
错误2:GetOutputTensor方法保护级别限制
Interpreter.GetOutputTensor(int)是受保护的方法,外部无法直接调用,需要使用公开的GetOutputTensorData<T>方法直接获取输出数据。
修正后的代码
using UnityEngine; using TensorFlowLite; using System.IO; using System.Collections.Generic; using System; public class ObjectDetection : MonoBehaviour { [SerializeField] [FilePopup("*.tflite")] public string modelPath = "model.tflite"; [SerializeField] private TextAsset labelFile; [SerializeField] private Texture2D inputImage; private Interpreter interpreter; private List<string> labels; private const int IMAGE_SIZE = 224; private const int CHANNELS = 3; private void Start() { LoadModel(); LoadLabels(); PreprocessImage(); RunInference(); } private void LoadModel() { var options = new InterpreterOptions(); options.UseNNAPI = true; interpreter = new Interpreter(File.ReadAllBytes(modelPath), options); interpreter.AllocateTensors(); } private void LoadLabels() { labels = new List<string>(); using (StringReader reader = new StringReader(labelFile.text)) { string line; while ((line = reader.ReadLine()) != null) { labels.Add(line.Trim()); } } } private void PreprocessImage() { Texture2D resizedImage = ResizeImage(inputImage, IMAGE_SIZE, IMAGE_SIZE); Color32[] pixels = resizedImage.GetPixels32(); float[] imgArray = new float[IMAGE_SIZE * IMAGE_SIZE * CHANNELS]; for (int i = 0; i < pixels.Length; i++) { imgArray[i * 3] = pixels[i].r / 255.0f; imgArray[i * 3 + 1] = pixels[i].g / 255.0f; imgArray[i * 3 + 2] = pixels[i].b / 255.0f; } interpreter.SetInputTensorData(0, imgArray); } private void RunInference() { interpreter.Invoke(); float[] results = interpreter.GetOutputTensorData<float>(0); int maxIndex = 0; float maxProbability = 0f; for (int i = 0; i < results.Length; i++) { if (results[i] > maxProbability) { maxProbability = results[i]; maxIndex = i; } } if (maxIndex < labels.Count) { string predictedLabel = labels[maxIndex]; Debug.Log($"Predicted object: {predictedLabel}, Probability: {maxProbability:F2}"); } else { Debug.LogError("Predicted index out of label range!"); } } private Texture2D ResizeImage(Texture2D source, int width, int height) { RenderTexture rt = RenderTexture.GetTemporary(width, height, 24); RenderTexture.active = rt; Graphics.Blit(source, rt); Texture2D result = new Texture2D(width, height); result.ReadPixels(new Rect(0, 0, width, height), 0, 0); result.Apply(); RenderTexture.active = null; RenderTexture.ReleaseTemporary(rt); return result; } }
额外注意事项
- 确保已正确导入TensorFlow Lite for Unity包(可通过Unity Package Manager安装官方包)。
- 模型文件需放在
StreamingAssets目录下,加载路径需调整为Path.Combine(Application.streamingAssetsPath, modelPath),否则导出APK后可能无法找到模型。 - 部分模型的输入预处理范围可能不同(如归一化到[-1,1]),需与训练模型时的预处理逻辑保持一致。
- 导出APK时,需在Player Settings中启用相应的权限,并确保TFLite的原生库被正确打包。
内容的提问来源于stack exchange,提问作者Eldhose Kurian
相关产品推荐
相关产品推荐

