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

在C#中加载并使用Teachable Machine导出的TensorFlow图像分类模型求助

嘿,我完全懂你现在卡在C#里用Teachable Machine导出的TensorFlow图像分类模型的困境!之前的提问被关闭确实闹心,我这就给你捋清楚步骤,附上实用的示例代码,保证能帮你搞定这个事儿~

在C#中加载并使用Teachable Machine导出的TensorFlow图像分类模型

一、先做好准备工作

首先得明确Teachable Machine导出的模型格式,一般常用的有两种:TensorFlow SavedModel 和 TensorFlow Lite (TFLite)。针对不同格式,C#里要用的依赖库不一样:

  • 要是用SavedModel:安装TensorFlow.NET+TensorFlow.Keras NuGet包
  • 要是用TFLite:安装TensorFlowLite.NET NuGet包

另外,导出模型的时候一定要把**标签文件(labels.txt)**一起下载下来,不然模型输出的数字索引没法转成你能看懂的分类名称。把模型文件和标签文件放到项目里后,记得设置它们的“复制到输出目录”为“如果较新则复制”,这样运行时才能找到文件。

二、推荐方案:加载TensorFlow Lite模型(轻量简洁)

TFLite模型体积小、推理快,适合桌面或移动端场景,先给你这个更实用的示例:

完整代码实现

using System;
using System.IO;
using System.Linq;
using TensorFlowLite;
using System.Drawing;

class TFLiteImageClassifier
{
    private readonly Interpreter _modelInterpreter;
    private readonly string[] _categoryLabels;
    private readonly int _requiredImgHeight;
    private readonly int _requiredImgWidth;
    private readonly float[] _inputDataBuffer;

    public TFLiteImageClassifier(string modelFilePath, string labelsFilePath)
    {
        // 加载分类标签
        _categoryLabels = File.ReadAllLines(labelsFilePath);

        // 初始化TFLite解释器
        var interpreterOptions = new InterpreterOptions();
        _modelInterpreter = new Interpreter(File.ReadAllBytes(modelFilePath), interpreterOptions);
        _modelInterpreter.AllocateTensors();

        // 获取模型要求的输入尺寸(一般是[1, 高, 宽, 3],对应批量1、图像高宽、RGB通道)
        var inputTensor = _modelInterpreter.GetInputTensor(0);
        var inputShape = inputTensor.Shape;
        _requiredImgHeight = (int)inputShape[1];
        _requiredImgWidth = (int)inputShape[2];
        _inputDataBuffer = new float[inputShape.Size];
    }

    public string ClassifySingleImage(string imageFilePath)
    {
        // 预处理图像:调整尺寸+像素归一化(Teachable Machine默认要求0-1范围)
        using var originalImg = new Bitmap(imageFilePath);
        using var resizedImg = new Bitmap(originalImg, _requiredImgWidth, _requiredImgHeight);

        // 把图像像素转成模型需要的float数组
        int bufferIndex = 0;
        for (int y = 0; y < resizedImg.Height; y++)
        {
            for (int x = 0; x < resizedImg.Width; x++)
            {
                var pixel = resizedImg.GetPixel(x, y);
                _inputDataBuffer[bufferIndex++] = pixel.R / 255f;
                _inputDataBuffer[bufferIndex++] = pixel.G / 255f;
                _inputDataBuffer[bufferIndex++] = pixel.B / 255f;
            }
        }

        // 喂数据给模型并运行推理
        _modelInterpreter.SetInputTensorData(0, _inputDataBuffer);
        _modelInterpreter.Invoke();

        // 获取输出结果,找到概率最高的分类
        var outputResults = _modelInterpreter.GetOutputTensor(0).DataAsFloatArray;
        int topResultIndex = outputResults
            .Select((probability, index) => (probability, index))
            .OrderByDescending(item => item.probability)
            .First().index;

        return _categoryLabels[topResultIndex];
    }

    public void Dispose()
    {
        _modelInterpreter.Dispose();
    }
}

// 调用示例
class Program
{
    static void Main(string[] args)
    {
        string modelPath = "model.tflite";
        string labelsPath = "labels.txt";
        string testImagePath = "your_test_image.jpg";

        using var classifier = new TFLiteImageClassifier(modelPath, labelsPath);
        string classificationResult = classifier.ClassifySingleImage(testImagePath);
        Console.WriteLine($"识别结果:{classificationResult}");
    }
}

三、备选方案:加载TensorFlow SavedModel

如果你导出的是SavedModel格式,用TensorFlow.NET来实现,代码如下:

完整代码实现

using System;
using System.IO;
using System.Linq;
using TensorFlow;
using TensorFlow.Keras.Preprocessing.Image;

class SavedModelImageClassifier
{
    private readonly TFSession _inferenceSession;
    private readonly TFGraph _modelGraph;
    private readonly string[] _categoryLabels;
    private readonly int _requiredImgHeight;
    private readonly int _requiredImgWidth;

    public SavedModelImageClassifier(string modelDirPath, string labelsFilePath)
    {
        // 加载分类标签
        _categoryLabels = File.ReadAllLines(labelsFilePath);

        // 加载SavedModel
        _modelGraph = new TFGraph();
        _modelGraph.ImportSavedModel(modelDirPath, new[] { "serve" }, null);
        _inferenceSession = new TFSession(_modelGraph);

        // 获取模型输入尺寸(输入节点名可能需要调整,用saved_model_cli工具可查看)
        var inputOp = _modelGraph["serving_default_input_1"];
        var inputShape = inputOp.Outputs[0].Shape;
        _requiredImgHeight = (int)inputShape[1];
        _requiredImgWidth = (int)inputShape[2];
    }

    public string ClassifySingleImage(string imageFilePath)
    {
        // 预处理图像:调整尺寸+转成模型需要的张量格式
        var image = ImageDataGenerator.LoadImg(imageFilePath, targetSize: (_requiredImgHeight, _requiredImgWidth));
        var imageArray = ImageDataGenerator.ImageToArray(image);
        var inputTensor = TFIOUtils.CreateTensorFromImageArray(new[] { imageArray }, TFDataType.Float);

        // 运行推理(输出节点名可能需要调整,用saved_model_cli工具可查看)
        var runner = _inferenceSession.GetRunner();
        runner.AddInput(_modelGraph["serving_default_input_1"][0], inputTensor)
              .Fetch(_modelGraph["StatefulPartitionedCall"][0]);

        var output = runner.Run();
        var outputResults = output[0].GetValue() as float[][];

        // 找到概率最高的分类
        int topResultIndex = outputResults[0]
            .Select((probability, index) => (probability, index))
            .OrderByDescending(item => item.probability)
            .First().index;

        return _categoryLabels[topResultIndex];
    }

    public void Dispose()
    {
        _inferenceSession.Dispose();
        _modelGraph.Dispose();
    }
}

// 调用示例
class Program
{
    static void Main(string[] args)
    {
        string modelDir = "./saved_model";
        string labelsPath = "labels.txt";
        string testImagePath = "your_test_image.jpg";

        using var classifier = new SavedModelImageClassifier(modelDir, labelsPath);
        string classificationResult = classifier.ClassifySingleImage(testImagePath);
        Console.WriteLine($"识别结果:{classificationResult}");
    }
}

几个要注意的小细节

  • 节点名称调整:SavedModel的输入输出节点名可能和示例里的不一样,你可以用TensorFlow的saved_model_cli工具查看:saved_model_cli show --dir ./saved_model --all,找到对应的节点名替换代码里的即可。
  • 图像预处理要求:Teachable Machine训练的模型一般要求输入是RGB格式,尺寸和你训练时设置的一致,像素值归一化到0-1(少数模型是-1到1,看你训练时的配置)。
  • 依赖版本兼容:安装NuGet包时尽量选稳定版本,确保TensorFlow.NET和相关依赖的版本匹配,避免出现奇怪的报错。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 08:58:23