手把手部署YOLOv5到RK3588安卓端:NPU加速与JNI/C/Kotlin接口开发指南

一、本文的目标

本文将rknn_model_zoo中yolov5的C语言例子迁移到Android应用中,让上层应用通过JNI直接调用C接口完成一张图片的目标识别。
本App上层应用将采用Kotlin编程,yolov5 C语言部分使用NDK编译,中间通过JNI调用。主要功能为在界面选择一张图片,用yolov5识别图片中的目标。
自带的android例子直接调用摄像头动态目标识别,二者略有区别。

二、开发环境说明

  • 主机系统:Windows 11
  • 目标设备:搭载RK3588芯片的安卓开发板
  • 核心工具:Android Studio Koala | 2024.1.1 Patch 2,NDK 27.0

三、NDK简介

原生开发套件 (NDK) 是一套Android开发工具,使开发者能够在 Android 应用中使用 C 和 C++ 代码。
在实践本章内容前需要了解NDK工具的使用,请参考我的上一篇文章《2025年的Android NDK 快速开发入门》

四、JNI简介

JNI(Java Native Interface)技术是Java平台的重要跨语言交互机制,其核心功能如下:

  • 双向互操作:实现Java/Kotlin与C/C++代码的双向调用
  • 数据类型映射:自动处理基础类型转换(jint↔int),复杂类型需手动处理(jobject↔C结构体)
  • 异常传播:本地代码可抛出Java异常,Java层可捕获处理
    双向互操作
  • Java → Native:通过 native 关键字声明方法,由 JVM 动态链接到本地函数
  • Native → Java:通过 JNIEnv 提供的反射式 API 操作 Java 对象
  • 数据桥接:所有跨语言数据需通过 JNI 类型系统转换(如 jint → int)
    数据桥接:类型转换被定义在jni.h头文件中,该文件可以在NDK目录中找到:$NDK_ROOT/toolchains/llvm/prebuilt/linux-x86_64/sysroot/usr/include/jni.h。
/* Primitive types that match up with Java equivalents. */
typedef uint8_t  jboolean; /* unsigned 8 bits */
typedef int8_t   jbyte;    /* signed 8 bits */
typedef uint16_t jchar;    /* unsigned 16 bits */
typedef int16_t  jshort;   /* signed 16 bits */
typedef int32_t  jint;     /* signed 32 bits */
typedef int64_t  jlong;    /* signed 64 bits */
typedef float    jfloat;   /* 32-bit IEEE 754 */
typedef double   jdouble;  /* 64-bit IEEE 754 */

重要的结构体JNINativeInterface
JNINativeInterface 结构体用于操作Java对象和类。

typedef struct JNINativeInterface {
   
    jint        (*GetVersion)(JNIEnv*);
    jclass      (*FindClass)(JNIEnv*, const char*);
    // 包含367个函数指针的完整结构体
} JNINativeInterface;

对象操作

struct JNINativeInterface {
   
    // 创建对象
    jobject (*NewObject)(JNIEnv*, jclass, jmethodID, ...);

    // 调用方法
    void (*CallVoidMethod)(JNIEnv*, jobject, jmethodID, ...);
    jint (*CallIntMethod)(JNIEnv*, jobject, jmethodID, ...);

    // 访问字段
    jfieldID (*GetFieldID)(JNIEnv*, jclass, const char*, const char*);
    jint (*GetIntField)(JNIEnv*, jobject, jfieldID);
};

数组和字符串处理

// 操作数组
jintArray (*NewIntArray)(JNIEnv*, jsize);
jint* (*GetIntArrayElements)(JNIEnv*, jintArray, jboolean*);

// 操作字符串
jstring (*NewStringUTF)(JNIEnv*, const char*);
const char* (*GetStringUTFChars)(JNIEnv*, jstring, jboolean*);

五、应用的简单说明

本应用只完成一个功能,就是选择图片后进行yolov5的目标检测并显示出结果,大致流程如图:

六、设计和开发

0. 新建kotlin项目

创建一个空界面的kotlin项目。MainActivity作为入口,再新建包ui.activity和yolo,并在activity包下创建RKNNYolov5Activity。

1.接口设计

本例中准备在native层暴露三个方法,分别是初始化、识别和释放。
kotlin层先创建接口
在yolo包下创建InferenceWrapper类:

package com.linc.rknn.yolo

import android.graphics.Bitmap

class InferenceWrapper {
   
    companion object {
   
        init {
   
            System.loadLibrary("rknn_yolov5")
        }
    }

    external fun init(modelPath: String, labelListPath: String): Boolean

    external fun detect(srtBitmap: Bitmap): Boolean

    external fun release(): Boolean
}

native层随后创建对应接口
在src->main下新建cpp目录,并新建一个cpp文件叫native-lib.cpp。
对应按规则直接写Cpp对应的方法,如下:

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>


extern <
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值