DAMO-YOLO模型部署到移动端:Android集成指南
本文介绍了如何在星图GPU平台上自动化部署DAMO-YOLO智能视觉探测系统镜像,实现移动端实时目标检测。该镜像能够快速识别摄像头画面中的行人、车辆等对象,适用于安防监控、智能交通等场景,显著提升移动设备的视觉分析能力。
DAMO-YOLO模型部署到移动端:Android集成指南
1. 引言
想不想在手机上实现实时目标检测?比如用手机摄像头就能识别行人、车辆、宠物?DAMO-YOLO作为阿里巴巴推出的高性能检测框架,在精度和速度方面都有不错的表现。今天我就带大家一步步把这个模型部署到Android设备上,让你也能在手机上玩转目标检测。
整个过程其实没想象中那么复杂,只要跟着步骤走,基本上半小时就能跑起来。我会从模型转换开始,讲到Android项目的集成,最后还会分享一些性能优化的技巧。无论你是Android开发新手还是有一定经验的开发者,都能跟着完成。
2. 环境准备与工具安装
开始之前,我们需要准备一些必要的工具。别担心,都是免费的开源工具。
首先确保你的开发环境有Python 3.7或更高版本,然后安装这些Python包:
pip install onnx onnxruntime onnx-simplifier
pip install opencv-python
pip install torch torchvision
对于Android开发部分,你需要:
- Android Studio最新版本
- Android NDK(建议使用21.x版本)
- 一台Android手机(建议Android 8.0以上)
3. 模型转换与优化
3.1 从PyTorch到ONNX
DAMO-YOLO官方提供了预训练模型,我们需要先把它转换成ONNX格式,这样才能在移动端使用。
import torch
from models.damo_yolo import DAMOYOLO
# 加载预训练模型
model = DAMOYOLO(model_type='s') # 可以选择't', 's', 'm'等不同尺寸
checkpoint = torch.load('damo_yolo_s.pth', map_location='cpu')
model.load_state_dict(checkpoint['model'])
model.eval()
# 定义输入尺寸
input_size = (1, 3, 640, 640) # batch, channels, height, width
# 导出为ONNX
dummy_input = torch.randn(input_size)
torch.onnx.export(
model,
dummy_input,
"damo_yolo_s.onnx",
opset_version=11,
input_names=['input'],
output_names=['output'],
dynamic_axes={'input': {0: 'batch_size'}, 'output': {0: 'batch_size'}}
)
3.2 ONNX模型简化
转换后的ONNX模型可能包含一些可以优化的节点,我们用onnx-simplifier来简化:
python -m onnxsim damo_yolo_s.onnx damo_yolo_s_sim.onnx
4. Android项目集成
4.1 创建Android项目
在Android Studio中创建一个新项目,选择Native C++模板。这样会自动配置好NDK环境。
4.2 添加ONNX Runtime依赖
在app的build.gradle文件中添加ONNX Runtime依赖:
dependencies {
implementation 'com.microsoft.onnxruntime:onnxruntime-android:1.12.0'
// 其他依赖...
}
4.3 准备模型文件
把简化后的ONNX模型文件(damo_yolo_s_sim.onnx)放到app/src/main/assets目录下。如果没有assets目录,就自己创建一个。
5. 实现推理代码
5.1 初始化ONNX Runtime
public class ObjectDetector {
private OrtEnvironment environment;
private OrtSession session;
public void initialize(Context context) {
try {
environment = OrtEnvironment.getEnvironment();
OrtSession.SessionOptions options = new OrtSession.SessionOptions();
// 从assets加载模型
InputStream modelStream = context.getAssets().open("damo_yolo_s_sim.onnx");
byte[] modelData = readStream(modelStream);
session = environment.createSession(modelData, options);
} catch (Exception e) {
Log.e("ObjectDetector", "初始化失败", e);
}
}
private byte[] readStream(InputStream inputStream) throws IOException {
ByteArrayOutputStream buffer = new ByteArrayOutputStream();
int nRead;
byte[] data = new byte[16384];
while ((nRead = inputStream.read(data, 0, data.length)) != -1) {
buffer.write(data, 0, nRead);
}
return buffer.toByteArray();
}
}
5.2 图像预处理
public float[] preprocessImage(Bitmap bitmap) {
// 调整尺寸到640x640
Bitmap resizedBitmap = Bitmap.createScaledBitmap(bitmap, 640, 640, true);
float[] inputValues = new float[3 * 640 * 640];
int[] pixels = new int[640 * 640];
resizedBitmap.getPixels(pixels, 0, 640, 0, 0, 640, 640);
// 转换为CHW格式并归一化
for (int i = 0; i < pixels.length; i++) {
int pixel = pixels[i];
// 提取RGB通道并归一化到0-1
inputValues[i] = ((pixel >> 16) & 0xFF) / 255.0f; // R
inputValues[i + 640 * 640] = ((pixel >> 8) & 0xFF) / 255.0f; // G
inputValues[i + 2 * 640 * 640] = (pixel & 0xFF) / 255.0f; // B
}
return inputValues;
}
5.3 执行推理
public List<DetectionResult> detect(Bitmap bitmap) {
try {
float[] inputData = preprocessImage(bitmap);
long[] shape = {1, 3, 640, 640};
OnnxTensor inputTensor = OnnxTensor.createTensor(environment, FloatBuffer.wrap(inputData), shape);
// 执行推理
OrtSession.Result results = session.run(Collections.singletonMap("input", inputTensor));
// 处理输出结果
float[][] output = (float[][]) results.get(0).getValue();
return processOutput(output);
} catch (Exception e) {
Log.e("ObjectDetector", "推理失败", e);
return new ArrayList<>();
}
}
6. 后处理与结果解析
DAMO-YOLO的输出需要经过后处理才能得到最终的检测框和类别:
private List<DetectionResult> processOutput(float[][] output) {
List<DetectionResult> results = new ArrayList<>();
// output[0]包含所有检测结果,格式为[x_center, y_center, width, height, confidence, class_scores...]
for (float[] detection : output) {
float confidence = detection[4];
// 过滤低置信度检测
if (confidence > 0.5f) {
// 找到最大类别概率
int classId = -1;
float maxClassScore = 0;
for (int i = 5; i < detection.length; i++) {
if (detection[i] > maxClassScore) {
maxClassScore = detection[i];
classId = i - 5;
}
}
// 计算最终得分
float score = confidence * maxClassScore;
if (score > 0.5f) {
DetectionResult result = new DetectionResult();
result.x = detection[0];
result.y = detection[1];
result.width = detection[2];
result.height = detection[3];
result.confidence = score;
result.classId = classId;
results.add(result);
}
}
}
return results;
}
7. 性能优化技巧
在移动端部署模型,性能优化很重要。这里分享几个实用的技巧:
7.1 使用量化模型
ONNX Runtime支持量化模型,可以显著提升推理速度:
// 在初始化时设置量化选项
OrtSession.SessionOptions options = new OrtSession.SessionOptions();
options.addConfigEntry("session.optimized_model_filepath", "damo_yolo_s_quantized.onnx");
7.2 线程优化
// 设置线程数
options.addConfigEntry("session.intra_op_num_threads", "4");
options.addConfigEntry("session.inter_op_num_threads", "2");
7.3 内存优化
// 启用内存优化
options.setMemoryPatternOptimization(true);
options.setExecutionMode(OrtSession.SessionOptions.ExecutionMode.PARALLEL);
7.4 输入尺寸优化
根据实际需求调整输入尺寸,较小的输入尺寸会更快:
// 根据设备性能选择合适尺寸
int targetSize = isHighEndDevice() ? 640 : 320;
Bitmap resizedBitmap = Bitmap.createScaledBitmap(bitmap, targetSize, targetSize, true);
8. 实际效果与总结
整体用下来,DAMO-YOLO在移动端的表现还是挺不错的。在中端手机上,640x640的输入尺寸下,推理速度能到15-20FPS,完全能满足实时检测的需求。精度方面,对于常见的物体如人、车、动物等,检测效果都很好。
部署过程中可能会遇到一些坑,比如模型转换时的节点不支持问题,或者内存占用过高。这时候可以尝试简化模型结构,或者使用更小的模型变体(比如DAMO-YOLO-Tiny)。
如果你想要更好的性能,可以考虑使用TensorFlow Lite或者MNN等推理引擎,它们针对移动端有更多优化。不过ONNX Runtime的兼容性更好,适合快速上手。
最后建议在实际部署前,一定要在不同型号的手机上测试性能,确保兼容性和稳定性。好的开始是成功的一半,希望这篇指南能帮你顺利在Android上部署DAMO-YOLO模型!
获取更多AI镜像
想探索更多AI镜像和应用场景?访问 CSDN星图镜像广场,提供丰富的预置镜像,覆盖大模型推理、图像生成、视频生成、模型微调等多个领域,支持一键部署。
魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。
更多推荐


所有评论(0)