YOLOv5如何部署到移动端?Android端部署实战详解

2025-06发布1次浏览

YOLOv5 是一个非常流行的实时目标检测框架,其高效性和灵活性使其在移动设备上的部署变得越来越重要。本文将详细介绍如何将 YOLOv5 部署到 Android 端,并提供具体的实战步骤。


一、YOLOv5 模型准备

1.1 下载预训练模型

YOLOv5 提供了多种预训练模型(如 yolov5s.ptyolov5m.pt 等),这些模型可以在官方 GitHub 仓库中下载。选择适合移动端性能需求的模型(通常推荐使用较小的模型如 yolov5s)。

1.2 转换为 ONNX 格式

Android 端通常不直接支持 PyTorch 的 .pt 模型格式,因此需要将其转换为 ONNX 格式。以下是具体步骤:

  1. 安装依赖
    确保安装了最新版本的 PyTorch 和 ONNX。

    pip install torch torchvision onnx
    
  2. 转换代码
    使用以下 Python 脚本将 .pt 模型转换为 .onnx

    import torch
    from models.experimental import attempt_load
    
    # 加载模型
    model = attempt_load('yolov5s.pt', map_location=torch.device('cpu'))  # 替换为你的模型路径
    model.eval()
    
    # 导出为 ONNX 格式
    input_size = (1, 3, 640, 640)  # 输入尺寸
    dummy_input = torch.randn(input_size)
    torch.onnx.export(
        model,
        dummy_input,
        "yolov5s.onnx",
        opset_version=12,
        input_names=['images'],
        output_names=['output']
    )
    print("ONNX 文件导出成功!")
    

1.3 将 ONNX 转换为 TensorRT 或 TFLite

为了进一步优化性能,可以将 ONNX 模型转换为 TensorRT 或 TensorFlow Lite 格式。以下是两种方式的简要介绍:

  • TensorRT:适用于 NVIDIA GPU 设备,能够显著提升推理速度。
  • TFLite:更适合 Android 平台,兼容性强且易于集成。

本文将以 TFLite 为例进行详细说明。

  1. 安装依赖

    pip install tf-nightly
    
  2. 转换代码

    import tensorflow as tf
    
    # 加载 ONNX 模型并转换为 TensorFlow SavedModel
    model = tf.saved_model.load('yolov5s_saved_model')
    
    # 转换为 TFLite 格式
    converter = tf.lite.TFLiteConverter.from_saved_model('yolov5s_saved_model')
    tflite_model = converter.convert()
    
    # 保存 TFLite 文件
    with open('yolov5s.tflite', 'wb') as f:
        f.write(tflite_model)
    print("TFLite 文件导出成功!")
    

二、Android 端集成与部署

2.1 添加依赖

在 Android 项目中,确保添加了 TensorFlow Lite 的依赖项。编辑 build.gradle 文件:

dependencies {
    implementation 'org.tensorflow:tensorflow-lite:2.10.0'
    implementation 'org.tensorflow:tensorflow-lite-gpu:2.10.0' // 可选:GPU 加速
}

2.2 加载模型

将生成的 yolov5s.tflite 文件放入 assets 目录中,并通过以下代码加载模型:

import org.tensorflow.lite.Interpreter;

// 加载模型
InputStream inputStream = getAssets().open("yolov5s.tflite");
File file = new File(getCacheDir(), "yolov5s.tflite");
FileOutputStream fileOutputStream = new FileOutputStream(file);
byte[] buffer = new byte[1024];
int read;
while ((read = inputStream.read(buffer)) != -1) {
    fileOutputStream.write(buffer, 0, read);
}
fileOutputStream.close();
inputStream.close();

Interpreter interpreter = new Interpreter(file);

2.3 数据预处理

YOLOv5 模型要求输入图像为固定大小(如 640x640),并且需要归一化处理。以下是一个简单的预处理方法:

public float[][][] preprocess(Bitmap bitmap) {
    int inputSize = 640; // 模型输入尺寸
    Bitmap resizedBitmap = Bitmap.createScaledBitmap(bitmap, inputSize, inputSize, false);

    float[][][] input = new float[1][inputSize][inputSize][3];
    for (int y = 0; y < inputSize; y++) {
        for (int x = 0; x < inputSize; x++) {
            int pixel = resizedBitmap.getPixel(x, y);
            input[0][y][x][0] = (Color.red(pixel) / 255.0f); // R
            input[0][y][x][1] = (Color.green(pixel) / 255.0f); // G
            input[0][y][x][2] = (Color.blue(pixel) / 255.0f); // B
        }
    }
    return input;
}

2.4 推理与后处理

通过 Interpreter.run() 方法执行推理,并对输出结果进行解析和绘制边界框。

  1. 推理代码

    float[][][] input = preprocess(bitmap);
    float[][] output = new float[1][25200]; // 输出维度根据模型调整
    interpreter.run(input, output);
    
  2. 后处理 解析输出结果并绘制边界框。YOLOv5 的输出包含多个候选框,需要通过非极大值抑制(NMS)筛选最终结果。以下是 NMS 的伪代码流程图:

    graph TD
        A[开始] --> B[获取所有候选框]
        B --> C[计算每个框的置信度]
        C --> D[按置信度排序]
        D --> E[初始化空列表]
        E --> F[遍历候选框]
        F --> G{是否与已有框重叠?}
        G --是--> H[跳过当前框]
        G --否--> I[加入最终结果]
        I --> J[返回最终结果]
    

三、性能优化与注意事项

  1. 模型压缩
    使用量化技术(如 INT8 量化)减少模型大小和推理时间。

    converter.optimizations = [tf.lite.Optimize.DEFAULT]
    converter.target_spec.supported_types = [tf.int8]
    
  2. GPU 加速
    在支持 GPU 的设备上启用 TensorFlow Lite 的 GPU 委托:

    Interpreter.Options options = new Interpreter.Options();
    options.addDelegate(new GpuDelegate());
    Interpreter interpreter = new Interpreter(file, options);
    
  3. 内存管理
    确保在应用退出时释放模型资源,避免内存泄漏。