yolov8模型部署到安卓项目(非NCNN,使用ONNX运行时)

目前移动端常见的部署神经网络模型格式有onnx,也有ncnn,或者直接使用torch运行时执行pt文件,今天简单的讲一下如何直接部署onnx格式的yolov8模型,相比ncnn格式的转换,onnx模式不需要繁琐的手动下载第三方库,吐槽一下ncnn准备步骤实在是又臭又长,对萌新极不友好。

先声明本文不包括java版的NMS数据清理,如有需要,自己照下面文章的python代码自行转换

首先,我们已经有了yolov8模型的onnx格式,转换详情见我下面的文章pytorch下yolov8打包onnx模型并使用NMS对数据清洗(最后有完整代码)_onnx runtime + yolo + pytroch-CSDN博客icon-default.png?t=N7T8https://blog.csdn.net/qq_64809150/article/details/140436333?spm=1001.2014.3001.5501

目录

一、导入第三方依赖:

二、创建onnx模型处理类

三、创建activity进行测试

四、结果展示


 

一、导入第三方依赖:

implementation 'com.microsoft.onnxruntime:onnxruntime-android:latest.release'

 将上述代码添加至build.gradle中的dependencies下面

二、创建onnx模型处理类

import ai.onnxruntime.OnnxTensor;
import ai.onnxruntime.OrtEnvironment;
import ai.onnxruntime.OrtSession;
import ai.onnxruntime.OrtSession.Result;
import ai.onnxruntime.OrtException;

import java.nio.FloatBuffer;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class ModelInference {
    private OrtEnvironment env;
    private OrtSession session;

    public ModelInference(String modelPath) throws OrtException {
        env = OrtEnvironment.getEnvironment();//创建环境
        session = env.createSession(modelPath);//创建会话
    }
    //运行模型推理
    public float[][] runInference(float[] inputData) throws OrtException {
        long[] inputShape = {1, 3, 640, 640};
        OnnxTensor inputTensor = OnnxTensor.createTensor(env, FloatBuffer.wrap(inputData), inputShape);

        Result output = session.run(Collections.singletonMap("images", inputTensor));
        float[][][] outputArray = (float[][][]) output.get(0).getValue();

        return parseAndTransposeOutput(outputArray);
    }
    //数据处理
    private static float[][] parseAndTransposeOutput(float[][][] outputArray) {
        int numDetections = outputArray[0][0].length;  // 8400
        int detectionLength = outputArray[0].length;   // 7

        List<float[]> validDetections = new ArrayList<>(numDetections / 2);

        for (int i = 0; i < numDetections; i++) {
            if (outputArray[0][4][i] > 0.5) {
                float[] detection = new float[detectionLength];
                for (int j = 0; j < detectionLength; j++) {
                    detection[j] = outputArray[0][j][i];
                }
                validDetections.add(detection);
            }
        }

        float[][] transposedArray = new float[validDetections.size()][detectionLength];
        for (int i = 0; i < validDetections.size(); i++) {
            transposedArray[i] = validDetections.get(i);
        }

        return transposedArray;
    }

    public void close() throws OrtException {
        if (session != null) {
            session.close();
        }
        if (env != null) {
            env.close();
        }
    }
}

先创建onnx环境和会话,我的模型都放在assets目录下面,这个目录需要自己创建,使用environment.createSession创建会话,顺便提一嘴,options用于为onnx模型会话配置特定的参数和设置,影响会话的行为和性能,也可以不写,会自动使用默认值,下面是该方法的官方文档截图(参照官方文档你怎么处理都可以)

上述runInference方法对输入数据进行推理,再使用parseAndTransposeOutput方法将数据进行转置操作便于后续数据清洗,如果你看过我上一篇文章就可以猜到这个方法其实是为后面的NMS清洗数据噪声做准备。

三、创建activity进行测试

xml文件就一个ImageView,自己重命名就可以了,我自己写了一个NMS算法对推理后的数据进行处理,最后可以完美显示结果,这部分代码我已经用python的形式在上一篇文章里面给出来了,链接见本文开头,有本事的自己转换代码,没本事的找博主要。

import static com.example.growth.modelUtil.yolo.NMS.drawBoundingBoxes;
import static com.example.growth.modelUtil.yolo.NMS.nms;

import android.annotation.SuppressLint;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.widget.CompoundButton;
import android.widget.ImageView;
import android.widget.Switch;
import android.widget.TextView;

import androidx.appcompat.app.AppCompatActivity;

import com.example.growth.modelUtil.ReadAssets;
import com.example.growth.modelUtil.yolo.ImageUtils;
import com.example.growth.modelUtil.yolo.ModelInference;
import com.example.growth.modelUtil.yolo.NMS;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.List;
import java.util.stream.IntStream;

import ai.onnxruntime.OrtEnvironment;
import ai.onnxruntime.OrtException;
import ai.onnxruntime.OrtSession;

public class Yolov8Test extends AppCompatActivity {
    private static final String MODEL_PATH = "yolov8_best.onnx"; // 模型文件路径
    private static final int INPUT_SIZE = 640;
    private ImageView imageView;

    @SuppressLint("MissingInflatedId")
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_yolov8_test);

        imageView = findViewById(R.id.imageView);
        open();
    }
    private void open(){
        try {
            // 加载图像
            InputStream inputStream = getAssets().open("0304.JPG");
            Bitmap bitmap = BitmapFactory.decodeStream(inputStream);

            // 预处理图像
            Bitmap resizedBitmap = ImageUtils.resizeImage(bitmap, INPUT_SIZE, INPUT_SIZE);
            float[] inputData = ImageUtils.preprocessImage(resizedBitmap, INPUT_SIZE);

            // 加载模型并进行推理
            ModelInference modelInference = new ModelInference(ReadAssets.assetFilePath(this,MODEL_PATH));//getAssetFilePath(MODEL_PATH)
            float[][] new_array=modelInference.runInference(inputData);
            List<float[]> nmsDetections = nms(new_array, 0.1f);
            float[] list=drawBoundingBoxes(resizedBitmap, nmsDetections);
            float max=findMaxValueUsingStream(list);

            // 显示结果图像
            imageView.setImageBitmap(resizedBitmap);
        } catch (IOException | OrtException e) {
            e.printStackTrace();
        }
    }

四、结果展示

  • 7
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

焚詩作薪

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值