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

Teachable Machine导出的TFLite模型在Flutter中仅识别首个类别问题

Flutter中Teachable Machine模型识别异常的解决方案

问题分析

在Teachable Machine中测试正常的模型,迁移到Flutter使用flutter_tflite: ^1.0.1时出现识别异常,始终高置信度识别为类别1,核心原因是图像输入的预处理、旋转、尺寸匹配与模型预期不匹配。

修复步骤及代码调整

1. 匹配模型输入尺寸

Teachable Machine导出的图像分类模型默认输入尺寸为224x224(可在导出页面确认),需在runModelOnFrame中明确指定inputSize参数,确保图像被缩放到模型要求的尺寸。

2. 修正图像旋转角度

手机摄像头的传感器方向与UI显示方向不一致,需根据摄像头的实际传感器方向设置rotation参数,而非固定为0。

3. 确保CameraImage尺寸传递正确

部分设备的CameraImage输出会交换宽高,需根据传感器方向调整传递给模型的宽高值。

4. 验证标签文件一致性

检查labels.txt的类别顺序是否与Teachable Machine中训练的类别顺序完全一致,避免标签映射错误。

修改后的完整代码

import 'dart:math';

import 'package:camera/camera.dart';
import 'package:flutter/material.dart';
import 'package:flutter_tflite/flutter_tflite.dart';
import 'package:get/get.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:weeding_bot/models/object_model.dart';

class ScanController extends GetxController {
  @override
  void onInit() {
    super.onInit();
    initCamera();
    initTFLite();
  }

  @override
  void dispose() {
    super.dispose();
    cameraController.dispose();
    Tflite.close(); // 释放TFLite资源
  }

  List<ObjectModel> allObjects = [];
  late CameraController cameraController;
  late List<CameraDescription> cameras;
  // 根据Teachable Machine导出的模型参数调整输入尺寸
  final int modelInputSize = 224;

  var isCameraInitialized = false;
  var cameraCount = 0;
  var detectorBusy = false;

  initCamera() async {
    if (await Permission.camera.request().isGranted) {
      cameras = await availableCameras();
      cameraController = CameraController(cameras[0], ResolutionPreset.medium); // 降低分辨率提升检测性能
      await cameraController.initialize().then((value) {
        cameraController.startImageStream((image) {
          cameraCount++;
          if (cameraCount % 10 == 0) {
            cameraCount = 0;
            objectDetector(image);
          }
        });
        update();
      });
      isCameraInitialized = true;
      update();
    } else {
      debugPrint("未获取相机权限");
    }
    update();
  }

  objectDetector(CameraImage frame) async {
    try {
      if (detectorBusy) {
        debugPrint("检测器繁忙,跳过当前帧");
        return;
      }
      detectorBusy = true;

      // 根据传感器方向调整旋转角度和宽高
      final int rotation = cameraController.description.sensorOrientation;
      final int imageWidth = rotation == 90 || rotation == 270 ? frame.height : frame.width;
      final int imageHeight = rotation == 90 || rotation == 270 ? frame.width : frame.height;

      var detector = await Tflite.runModelOnFrame(
          bytesList: frame.planes.map((e) => e.bytes).toList(),
          imageHeight: imageHeight,
          imageWidth: imageWidth,
          imageMean: 127.5, // 匹配Teachable Machine的预处理规则
          imageStd: 127.5,
          rotation: rotation, // 使用摄像头实际旋转角度
          numResults: 5,
          threshold: 0.1,
          inputSize: modelInputSize); // 指定模型输入尺寸

      if (detector != null) {
        debugPrint("识别结果: $detector");
        // 可选:更新UI显示识别结果
        // allObjects = detector.map((item) => ObjectModel.fromMap(item)).toList();
        // update();
      }
    } catch (e) {
      debugPrint("识别错误: $e");
    } finally {
      detectorBusy = false;
    }
  }

  initTFLite() async {
    await Tflite.loadModel(
      model: "assets/trainedModel/weedDetector.tflite",
      labels: "assets/trainedModel/labels.txt",
    );
  }
}

额外排查点

  • 检查assets目录下的模型和标签文件是否正确配置在pubspec.yaml中:
    assets:
      - assets/trainedModel/weedDetector.tflite
      - assets/trainedModel/labels.txt
    
  • 测试时确保光线充足,拍摄目标与Teachable Machine训练时的场景、角度尽量一致
  • 若仍有问题,可尝试将图像转换为RGB格式后再输入模型(flutter_tflite支持直接传入RGB字节数组)

内容的提问来源于stack exchange,提问作者Juan Pablo Arango Lizcano

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.08 19:55:05