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

如何将Firebase上的Custom ML Kit TFLite模型集成到Flutter Android端

Flutter Android端集成Firebase Custom ML Kit自定义TFLite图像分类模型实现步骤

所有代码片段的添加位置均明确标注,按顺序配置即可跑通。

1 基础环境配置

  • 先确认你已经完成Firebase核心接入:将Firebase控制台下载的google-services.json文件放到项目android/app目录下,这步是所有Firebase服务的基础,没完成的先补。
  • 打开项目根目录下的pubspec.yaml文件,在dependencies块下添加以下依赖,之后执行flutter pub get拉取包:
dependencies:
  flutter:
    sdk: flutter
  firebase_core: ^2.24.2 # 和你项目其他Firebase依赖版本保持一致即可
  firebase_ml_model_downloader: ^0.2.4+16 # 负责拉取你托管在Firebase上的自定义模型
  tflite_flutter: ^0.10.4 # 负责TFLite模型推理
  image: ^4.1.3 # 负责图片解码、尺寸调整等预处理操作
  • 打开android/app/build.gradle文件,修改defaultConfig块下的minSdkVersion为21及以上,ML Kit自定义模型不支持更低版本:
android {
    defaultConfig {
        minSdkVersion 21
        // 原有其他配置保持不动
    }
}

如果后续运行时报libc++_shared.so冲突错误,就在上述android块下追加packagingOptions配置:

packagingOptions {
  pickFirst 'lib/x86_64/libc++_shared.so'
  pickFirst 'lib/arm64-v8a/libc++_shared.so'
  pickFirst 'lib/armeabi-v7a/libc++_shared.so'
}

2 模型加载逻辑

这部分代码写在你需要触发图像分类功能的页面(比如拍照/选图页面)对应的State类中,不要写在main函数里,会导致启动白屏。

  • 先在State类里定义状态变量:
// 存储从Firebase下载到本地的模型文件
File? _localModelFile;
// 标记模型是否加载完成
bool _isModelReady = false;
// 替换成你在Firebase ML控制台上传模型时填写的自定义名称,大小写必须完全一致
final String _deployedModelName = "your_tflite_model_name";
  • 在State的initState生命周期里调用模型加载方法,页面初始化时自动拉取模型:
@override
void initState() {
  super.initState();
  _fetchModelFromFirebase();
}

Future<void> _fetchModelFromFirebase() async {
  try {
    // 拉取规则:优先使用本地缓存模型,后台静默检查更新
    final customModel = await FirebaseModelDownloader.instance.getModel(
      _deployedModelName,
      FirebaseModelDownloadType.localModelUpdateInBackground,
      FirebaseModelDownloadConditions(
        androidChargingRequired: false,
        androidWifiRequired: false,
        androidDeviceIdleRequired: false,
      ),
    );
    _localModelFile = customModel.file;
    setState(() {
      _isModelReady = true;
    });
  } catch (e) {
    debugPrint("模型拉取失败: $e");
  }
}

3 图像预处理与推理逻辑

这部分代码写在同一个State类里,在用户选完图片/拍完照拿到图片File对象之后调用即可。

  • 先实现图像预处理方法,把原始图片转换成模型要求的输入格式,注意所有预处理参数必须和你训练模型时的参数完全一致,否则推理结果会完全错误:
Future<Uint8List> _imagePreprocess(File rawImageFile) async {
  // 解码原始图片
  final rawBytes = await rawImageFile.readAsBytes();
  final originalImg = img.decodeImage(rawBytes);
  if (originalImg == null) throw Exception("图片解码失败");

  // 替换成你模型要求的输入尺寸,比如常见的224*224、320*320
  const int inputSize = 224;
  // 调整图片尺寸匹配模型输入
  final resizedImg = img.copyResize(originalImg, width: inputSize, height: inputSize);

  // 按模型要求转换像素格式、做归一化,以下是通用0-1归一化示例,按你训练时的逻辑修改
  final convertedInput = Float32List(1 * inputSize * inputSize * 3);
  int pixelPos = 0;
  for (int y = 0; y < inputSize; y++) {
    for (int x = 0; x < inputSize; x++) {
      final currentPixel = resizedImg.getPixel(x, y);
      // 如果你的模型要求归一化到-1~1,就改成 (currentPixel.r / 127.5) - 1 这种逻辑
      convertedInput[pixelPos++] = currentPixel.r / 255.0;
      convertedInput[pixelPos++] = currentPixel.g / 255.0;
      convertedInput[pixelPos++] = currentPixel.b / 255.0;
    }
  }
  return convertedInput.buffer.asUint8List();
}
  • 实现推理方法,输出排序后的分类结果:
Future<List<Map<String, dynamic>>> _runClassification(File inputImage) async {
  if (!_isModelReady || _localModelFile == null) {
    throw Exception("模型未加载完成,请稍后重试");
  }
  // 加载本地模型初始化解释器
  final tfliteInterpreter = Interpreter.fromFile(_localModelFile!);
  // 预处理输入图片
  final modelInput = await _imagePreprocess(inputImage);

  // 替换成你模型的输出维度,比如1000分类就写[1,1000]
  final modelOutput = List.filled(1 * 1000, 0.0).reshape([1, 1000]);
  // 执行推理
  tfliteInterpreter.run(modelInput, modelOutput);
  // 推理完成后及时关闭解释器释放内存
  tfliteInterpreter.close();

  // 替换成你训练模型时对应的标签列表,顺序必须和训练时完全一致
  const labelList = ["标签1", "标签2", "标签3" /* 补全所有分类标签 */];
  List<Map<String, dynamic>> predictResult = [];
  for (int i = 0; i < labelList.length; i++) {
    predictResult.add({
      "label": labelList[i],
      "confidence": modelOutput[0][i]
    });
  }
  // 按置信度从高到低排序
  predictResult.sort((a, b) => b["confidence"].compareTo(a["confidence"]));
  return predictResult;
}

4 常见问题排查

  • 模型拉取失败:首先检查设备网络是否正常,其次检查模型名称是否和Firebase控制台填写的完全一致,不要有大小写、空格错误。
  • 推理结果不准:90%以上的情况是预处理逻辑和训练时不匹配,重点检查resize尺寸、归一化公式、通道顺序(部分模型用BGR顺序)、标签顺序。
  • 运行卡顿:图像预处理和推理逻辑不要放在主线程执行,如果图片尺寸大、模型体积大,可以用compute方法放到后台isolate执行。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 13:12:18