随着移动设备计算能力的提升,越来越多的深度学习模型被部署到移动端,以实现实时、低延迟的应用场景。YOLO系列的在目标检测任务中表现出色,具有精度高、速度快的优势。本文将详细介绍如何基于NCNN框架 ,在Android平台 上高效部署YOLOv8目标检测模型,并结合OpenCVVulkan加速实现高性能推理。

效果展示:

1. 准备工作

步骤一: 下载YOLOv8源码进行训练模型,环境配置以及训练方法在此不做赘述,可以参考主页-Ultralytics YOLOv8文档进行。

项目下载地址:YOLOv8-github
官方快速入门:YOLOv8-文档

步骤二: 安装 Android Studio (https://developer.android.google.cn/),非本文重点,不做赘述。

步骤三:准备项目:①下载 ncnn-android-yolov8,官方地址:https://github.com/FeiGeChuanShu/ncnn-android-yolov8

在这里插入图片描述
② 下载 opencv-mobile: https://github.com/nihui/opencv-mobile/releases 和 ncnn-android-vulkan: https://github.com/Tencent/ncnn/releases

将上面下载好的两个压缩包解压后放入该位置:ncnn-android-yolov8\app\src\main\jni\

2. 模型转化

2.1 修改源码

经过训练模型之后,默认得到的文件格式为.pt后缀文件,通过模型导出Ultralytics YOLO文档可以得知训练后可以导出多种不同模型文件。但是,值得注意的是:在转换前需要对项目源码作出一些修改,待修改的内容在ncnn-android-yolov8-main/doc/ 中有显示,如使用检测任务则修改 c2f.jpgDetect.jpg两张图片上的内容。即把ultralytics项目中的下列函数修改:

  1. ultralytics/ultralytics/nn/modules/head.py:注释Detect类下forward方法内所有内容并添加代码

    shape = x[0].shape  # BCHW
    for i in range(self.nl):x[i] = torch.cat((self.cv2[i](x[i]), self.cv3[i](x[i])), 1)
    if self.training:  # Training pathreturn x
    elif self.dynamic or self.shape != shape:self.anchors, self.strides = (x.transpose(0, 1) for x in make_anchors(x, self.stride, 0.5))self.shape = shapepred = torch.cat([xi.view(shape[0], self.no, -1) for xi in x], 2).permute(0, 2, 1)
    return pred
    

    在这里插入图片描述

  2. ultralytics/ultralytics/nn/modules/block.py:注释C2f类下forward方法内所有内容并添加代码

    x = self.cv1(x)
    x = [x, x[:, self.c:, ...]]
    x.extend(m(x[-1]) for m in self.m)
    x.pop(1)
    return self.cv2(torch.cat(x, 1))
    

    在这里插入图片描述
    注:恢复原代码即可重新训练!!

2.2 pt转onnx

新建文件pt_to_onnx.py,填入自己的模型路径运行:

# 将模型导出为ONNX 格式
from ultralytics import YOLOmodel = YOLO(r"模型路径")
success = model.export(format="onnx", imgsz=320, half=True, opset=12)

在这里插入图片描述
点击网址 https://netron.app,导入onnx模型:可以看到输入名称和输出名称:
在这里插入图片描述
输入名称images,输出名称output0

2.3 onnx转ncnn

  1. 安装Visual Studio

  2. 下载并解压ncnn-YYYYMMDD-windows-vsXXXX.zip(vs后的数字应当要与本地Visual Studio版本保持一致。):https://github.com/Tencent/ncnn/releases
    在这里插入图片描述

  3. 打开文件夹 \ncnn-20250503-windows-vs2022\x64\bin,可以看到应用程序onnx2ncnn.exe
    在这里插入图片描述

  4. 进入该文件夹(cmd):
    在这里插入图片描述

  5. 输入(将yolov8n换成自己的模型路径名)并运行

    onnx2ncnn E:\OCR_Project\yolov8n.onnx yolov8n.param yolov8n.bin
    

    在这里插入图片描述
    可以看到 \ncnn-20250503-windows-vs2022\x64\bin 文件夹下多出来两个文件,
    在这里插入图片描述

2.4 修改项目代码

将转换后的模型文件粘贴至\ncnn-android-yolov8-main\ncnn-android-yolov8\app\src\main\assets

Android studio打开\ncnn-android-yolov8-main\ncnn-android-yolov8
在这里插入图片描述

  1. 修改\ncnn-android-yolov8\app\src\main\jni\yolo.cpp:函数修改static const char* class_names[] 为模型的预测类别

    int Yolo::draw(cv::Mat& rgb, const std::vector<Object>& objects)
    {static const char* class_names[] = {"person", "bicycle", "car", "motorcycle", "airplane", "bus", "train", "truck", "boat", "traffic light","fire hydrant", "stop sign", "parking meter", "bench", "bird", "cat", "dog", "horse", "sheep", "cow","elephant", "bear", "zebra", "giraffe", "backpack", "umbrella", "handbag", "tie", "suitcase", "frisbee","skis", "snowboard", "sports ball", "kite", "baseball bat", "baseball glove", "skateboard", "surfboard","tennis racket", "bottle", "wine glass", "cup", "fork", "knife", "spoon", "bowl", "banana", "apple","sandwich", "orange", "broccoli", "carrot", "hot dog", "pizza", "donut", "cake", "chair", "couch","potted plant", "bed", "dining table", "toilet", "tv", "laptop", "mouse", "remote", "keyboard", "cell phone","microwave", "oven", "toaster", "sink", "refrigerator", "book", "clock", "vase", "scissors", "teddy bear","hair drier", "toothbrush"};
    

    在这里插入图片描述

  2. 修改 ex.input(“images”, in_pad); 和 ex.extract(“output”, out); 为模型输入输出名

    在这里插入图片描述

  3. 修改const int num_class为模型分类数量

    在这里插入图片描述

  4. 修改文件夹内模型匹配格式:

    在这里插入图片描述

  5. 修改\ncnn-android-yolov8\app\src\main\jni\yolov8ncnn.cpp:修改const char* modeltypes[] 为模型名。

    在这里插入图片描述

  6. 修改 const int target_sizes[]、const float mean_vals[][3]、const float norm_vals[][3] 代码行数匹配文件夹内模型数量

    在这里插入图片描述

  7. 修改\ncnn-android-yolov8\app\src\main\res\values\strings.xml

    在这里插入图片描述
    注:此修改仅调整下拉菜单中的选项显示名称,实际选项匹配由索引值完成,与名称无关。

2.5 编译运行

在这里插入图片描述

3. 画面清晰度

修改\ncnn-android-yolov8\app\src\main\jni\ndkcamera.cppAImageReader_new方法

在这里插入图片描述
在这里插入图片描述

4. 默认摄像头

修改\ncnn-android-yolov8\app\src\main\java\com\tencent\yolov8ncnn\MainActivity.java : private int facing(0:前置,1:后置)

在这里插入图片描述
修改 cnn-android-yolov8/app/src/main/res/layout/main.xml 文件即可调整APP界面布局,通过拖拽操作即可完成。

5. 总结展望

本文详细介绍了如何基于NCNN框架 在Android平台 上部署YOLOv8目标检测模型 的完整流程。从环境配置、模型转换、项目搭建到最终的调试运行,每一步都提供了清晰的操作指引和代码示例,帮助开发者快速实现YOLOv8在移动端的落地应用。

亮点总结

  • 使用NCNN框架实现高效的模型推理,兼容性强且性能优越;
  • 通过OpenCV-Mobile提升图像预处理效率;
  • 支持自定义训练模型的无缝替换,灵活应用于不同场景;
  • 实现了YOLOv8在移动端的实时视频检测功能,满足工业级需求。

展望

未来可进一步优化模型量化策略(如FP16/INT8),提升推理速度;同时结合Vulkan异构计算能力,进一步挖掘移动端GPU的潜力,实现更高帧率的目标检测体验。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/pingmian/88102.shtml
繁体地址,请注明出处:http://hk.pswp.cn/pingmian/88102.shtml
英文地址,请注明出处:http://en.pswp.cn/pingmian/88102.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

华为动态路由配置

问题描述&#xff1a;针对四个路由器在不同的网段场景中&#xff0c;对四个路由器进行动态路由配置。下面以如下场景为例&#xff0c;介绍详细配置过程。配置过程&#xff1a; 1、每个路由器的接口配置IP地址 路由器AR1中每个接口配置IP地址。 sys # 进入系统视图 interface g…

分布式事务解决方案(三)

在Java分布式系统领域&#xff0c;传统强一致性方案&#xff08;如2PC、3PC&#xff09;在高并发、复杂业务场景下暴露出性能瓶颈和阻塞问题。而Saga模式与事件溯源&#xff08;Event Sourcing&#xff09;作为更具弹性和扩展性的解决方案&#xff0c;逐渐成为分布式事务处理和…

【时时三省】(C语言基础)通过指针引用数组

山不在高&#xff0c;有仙则名。水不在深&#xff0c;有龙则灵。 ----CSDN 时时三省数组元素的指针一个变量有地址&#xff0c;一个数组包含若干元素&#xff0c;每个数组元素都在内存中占用存储单元&#xff0c;它们都有相应的地址。指针变量既然可以指向变量&#xff0c;当然…

【WEB】Polar靶场 21-25题 详细笔记

二十一.php very nicephp又是你 ,但是经过这么多次折磨后我感觉我已经有一点抗性了老规矩&#xff0c;先看知识点PHP 序列化是将 PHP 变量&#xff08;如对象、数组&#xff09;转换为字符串的过程&#xff0c;便于存储或传输。反序列化则是将字符串还原为原始变量。这在缓存、…

【Guava】1.0.设计虚拟机的方向

【Guava】1.0.设计虚拟机的方向虚拟机是什么&#xff1f;栈式虚拟机栈式虚拟机的优缺点题外话虚拟机是什么&#xff1f; 虚拟机&#xff08;VirtualMachine, VM&#xff09;是一种计算机程序或系统&#xff0c;它通过软件模拟物理计算机的硬件运行环境&#xff0c;使得多个操作…

[附源码+数据库+毕业论文]基于Spring+MyBatis+MySQL+Maven+jsp实现的高校实验室资源综合管理系统,推荐!

摘 要 现代经济快节奏发展以及不断完善升级的信息化技术&#xff0c;让传统数据信息的管理升级为软件存储&#xff0c;归纳&#xff0c;集中处理数据信息的管理方式。本高校实验室资源综合管理系统就是在这样的大环境下诞生&#xff0c;其可以帮助管理者在短时间内处理完毕庞大…

Spring Boot:影响事务回滚的几种情况

一、Controller 捕获异常导致事务失效 需求 我们有一个用户注册服务&#xff0c;注册时需要&#xff1a; 创建用户账户分配初始积分发送注册通知 这三个操作需要在同一个事务中执行&#xff0c;任何一步失败都要回滚。 错误示例&#xff1a;Controller 捕获异常导致事务失效 Re…

如何避免分布式爬虫被目标网站封禁?

在分布式爬虫的大规模数据采集场景中&#xff0c;避免被目标网站封禁的核心逻辑是&#xff1a;通过技术手段模拟真实用户行为&#xff0c;降低爬虫行为的可识别性&#xff0c;同时建立动态适配机制应对网站反爬策略的升级。以下从请求伪装、行为控制、资源管理、反爬对抗四个维…

Maven 打包排除特定依赖的完整指南(详细方法 + 示例)

前言 在使用 Maven 构建 Java 项目时&#xff0c;我们常常需要对项目的打包过程进行精细化控制&#xff0c;尤其是希望排除某些特定的依赖库。这可能是为了减小最终构建产物的体积、避免版本冲突&#xff0c;或者仅仅是为了满足不同环境下的部署需求。 本文将详细介绍如何在 Ma…

Terraform `for_each` 精讲:优雅地自动化多域名证书验证

大家好&#xff0c;在云原生和自动化运维的世界里&#xff0c;Terraform无疑是基础设施即代码&#xff08;IaC&#xff09;领域的王者。它强大的声明式语法让我们能够轻松地描述和管理云资源。然而&#xff0c;即使是经验丰富的工程师&#xff0c;在面对某些动态场景时也可能会…

C++标准库中各种互斥锁的用法 mutex

示例 仅供参考学习 #include <mutex> #include <shared_mutex> #include <thread> #include <chrono> #include <iostream> #include <vector>// // 1. std::mutex - 基本互斥锁 // void basic_mutex_example() {std::mutex mtx;int cou…

Android Handler机制与底层原理详解

Android 的 Handler 机制是跨线程通信和异步消息处理的核心框架&#xff0c;它构成了 Android 应用响应性和事件驱动模型的基础&#xff08;如 UI 更新、后台任务协调&#xff09;。其核心思想是 “消息队列 循环处理”。 核心组件及其关系Handler (处理器): 角色: 消息的发送…

jQuery JSONP:实现跨域数据交互的利器

jQuery JSONP&#xff1a;实现跨域数据交互的利器 引言 随着互联网的发展&#xff0c;跨域数据交互的需求日益增加。在Web开发中&#xff0c;由于同源策略的限制&#xff0c;直接通过XMLHttpRequest请求跨域数据会遇到诸多问题。而JSONP&#xff08;JSON with Padding&#xff…

Redis集群和 zookeeper 实现分布式锁的优势和劣势

在分布式系统中&#xff0c;实现分布式锁是确保多个节点间互斥访问共享资源的一种常见需求。Redis 集群 和 zookeeper 都可以用来实现这一功能&#xff0c;但它们有着各自不同的优势和劣势。 CAP 理论&#xff1a; 在设计一个分布式系统时&#xff0c;一致性&#xff08;Consis…

如何备份vivo手机中的联系人?

随着vivo移动设备在全球设立7个研发中心&#xff0c;vivo正在进入更多的国家。如今&#xff0c;越来越多的人开始使用vivo手机。以vivo X100为例&#xff0c;它配备了主摄像头和多个辅助摄像头&#xff0c;提供多样化的拍摄选项&#xff0c;并搭载了最新的FunTouch OS&#xff…

python脚本编程:使用BeautifulSoup爬虫库获取热门单机游戏排行榜

BeautifulSoup是一个便捷的解析html页面元素的python库&#xff0c;此处用来写一个简单的爬虫批量抓取国内游戏资讯网站的近期热门单机游戏排行榜。 网页来源如下所示代码 from bs4 import BeautifulSoup import requests# get web page web_url "https://www.3dmgame.co…

C#配置全面详解:从传统方式到现代配置系统

C#配置全面详解&#xff1a;从传统方式到现代配置系统 在软件开发中&#xff0c;配置是指应用程序运行时可调整的参数集合&#xff0c;如数据库连接字符串、API 地址、日志级别等。将这些参数从代码中分离出来&#xff0c;便于在不修改代码的情况下调整应用行为。C# 提供了多种…

数据中台架构解析:湖仓一体的实战设计

目录 一、数据中台与湖仓一体架构是什么 1. 数据中台 2. 湖仓一体架构 3. 湖仓一体在数据中台里的价值 二、湖仓一体架构的核心部件 1. 数据湖 2. 数据仓库 3. 数据集成工具 4. 数据分析与处理引擎 三、湖仓一体架构实战设计 1. 需求分析与规划 2. 数据湖建设 3. …

SQL Server表分区技术详解

表分区概述 表分区是将大型数据库表物理分割为多个较小单元的技术,逻辑上仍表现为单一实体。该技术通过水平分割数据显著提升查询性能,尤其针对TB级数据表可降低90%的响应时间。典型应用场景包含订单历史表、日志记录表等具有明显时间特征的业务数据,以及需要定期归档的审计…

WHIP(WebRTC HTTP Ingestion Protocol)详解

WHIP&#xff08;WebRTC HTTP Ingestion Protocol&#xff09;详解 WHIP&#xff08;WebRTC HTTP Ingestion Protocol&#xff09;是一种基于 HTTP 的协议&#xff0c;用于将 WebRTC 媒体流推送到媒体服务器&#xff08;如 SRS、Janus、LiveKit&#xff09;。它是为简化 WebRT…