You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Unity中使用TensorFlow Lite模型报错求助:GetOutputTensor无法访问等问题

Unity中TensorFlow Lite分类模型调用错误修复

问题背景

有一个以图像为输入的TensorFlow Lite分类模型,需要在Unity项目中使用。使用ChatGPT生成的代码后出现两个编译错误,此前用.h5模型结合Python在C#中可运行,但导出APK后失效,因此改用TensorFlow Lite方案。

错误信息

  1. Assets\Samples\Detection\Scripts\PythonBridge.cs(72,9): error CS0246: 找不到类型或命名空间名称‘Tensor’(是否缺少using指令或程序集引用?)
  2. 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;
    }
}

额外注意事项

  1. 确保已正确导入TensorFlow Lite for Unity包(可通过Unity Package Manager安装官方包)。
  2. 模型文件需放在StreamingAssets目录下,加载路径需调整为Path.Combine(Application.streamingAssetsPath, modelPath),否则导出APK后可能无法找到模型。
  3. 部分模型的输入预处理范围可能不同(如归一化到[-1,1]),需与训练模型时的预处理逻辑保持一致。
  4. 导出APK时,需在Player Settings中启用相应的权限,并确保TFLite的原生库被正确打包。

内容的提问来源于stack exchange,提问作者Eldhose Kurian

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.27 09:33:18