安卓利用tensorflow-lite使用yolov5训练的模型

2023-05-16

前言

作为使用yolov5后一次简单的尝试

准备工作

  • 通过yolov5训练出自己所需要的模型查看模型训练教程
  • 将模型通过tensorflow的python版转换,使用yolov5 6.1以上版本
  • 安卓端引入tensorflow远端依赖,并置入模型文件在项目工程里
    这里我并没有去看tensorflow的api,而是直接参考了yolov5-android

注意事项

  • 模型我全部用的是demo默认模型
  • 运行demo时请打开悬浮窗权限

配置gradle

需要执行cmake来生成通过jni调用的资源
在app目录下的CmakeList.txt文本可以查看具体配置
这里不过多描述,只描述构建过程
远程引入tensorflow依赖

    externalNativeBuild {
        cmake {
            path "CMakeLists.txt"
        }
    }
      defaultConfig {......
        ndk {
            abiFilters 'armeabi-v7a', 'arm64-v8a'
        }
    }
    dependencies {......
	 implementation 'org.tensorflow:tensorflow-lite:2.4.0'
 }

迁移文件

将在modle_tflite下的文件夹复制到如下图所示
将在main/cpp的文件夹也复制到如下图所示

在这里插入图片描述

postprocess.cpp文件提供了供java调用的检测函数,这里可以去参考Tensorflow官方网站,是将结果通过jni给回调至客户端

编写悬浮窗

使用了XToast,我是以library形式引入工程的

执行录制屏幕代码

使用的是官方api,MediaProjection,感兴趣可以去查找相关资料
注意在安卓10级以上需要启动一个前台服务才可以使用请添加图片描述
开启录屏部分代码

	// 顶部初始化
    private var mediaProjection: MediaProjection?=null
    private lateinit var projectionManager:MediaProjectionManager
    ......
    // 点击事件请求开始录屏
      binding.btnRecord.setOnClickListener {
             projectionManager =getSystemService(MEDIA_PROJECTION_SERVICE) as MediaProjectionManager
            val captureIntent= projectionManager.createScreenCaptureIntent();
            startActivityForResult(captureIntent,20);
        }
    ......
    // 和运行时权限申请一样,在onActivityResult回调里处理开始录屏事件
     override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)
        if (requestCode == 20 && resultCode == RESULT_OK) {
           FloatUtil.showFloatWindow(application).apply {
               contentImageView = this
           }
            mediaProjection = projectionManager.getMediaProjection(resultCode, data!!);
            //执行查看视图函数
            seeContent()
        }
    }    

开启录屏后,需要用到另外一个东西,就是mediaProjection的createVirtualDisplay函数,其实就是VirtualDisplay,创建一个虚拟显示器。mediaProjection的使用(转载)和关于VirtualDisplay的使用

    private fun seeContent() {
        mediaProjection?.apply {
            createDetector()//创建检测器
            createImageReader() //创建imageReader
            registerCallback(object :MediaProjection.Callback(){
                override fun onStop() {
                    super.onStop()
                }
            },handler)
			//使用createVirtuaDisplay函数,需要制定名称,宽和高,dpi,显示模式,surface,剩余两个参数可以为null
            dispalyD = createVirtualDisplay("ScreenImageReader",640,640,1000
            , DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR,imageReader.surface,object :VirtualDisplay.Callback(){
                    override fun onResumed() {
                        super.onResumed()
                    }

                    override fun onPaused() {
                        super.onPaused()
                    }

                    override fun onStopped() {
                        super.onStopped()
                    }
                },handler)
        }
    }

这里这里使用imageReader,imageReader它是包含一个surface的,并且它有一个setOnImageAvailableListener可以进行监听视图刷新,在刷新的时候去获取image对象,关于图片的边框添加和识别操作,可以看下面代码片段

  /**
     * 图片更新
     * 此处为回调函数
     * 交由handler处理
     */
    override fun onImageAvailable(p0: ImageReader?) {
        //利用handler
            p0?.apply {
                val message = Message()
                message.what = 0xdd
                message.obj = this
                handlerDelayImage.sendMessage(message)
                handlerDelayImage.obtainMessage()
            }
    }
   /**
     * 开始截屏并识别
     * 这个才是具体的处理函数
     */
    private fun startCacheAndSetInput(p0: ImageReader) {
        var nowImage:Image?=null
        try {
            nowImage = p0.acquireLatestImage()

        }catch (e:Exception){
            nowImage = p0.acquireLatestImage()
        }
        nowImage?.apply {
            val width = 640 //可选
            val height = 640
            val planes = planes
            val buffer: ByteBuffer = planes[0].buffer
            val pixelStride = planes[0].pixelStride
            val rowStride = planes[0].rowStride
            val rowPadding = rowStride - pixelStride * width
            var bitmap: Bitmap =
                Bitmap.createBitmap(width + rowPadding / pixelStride, height, Bitmap.Config.ARGB_8888)
            bitmap.copyPixelsFromBuffer(buffer)
            //这就是初始截图
            bitmap = Bitmap.createBitmap(bitmap, 0, 0, width, height)
            //开始检测
            detector.setInput(bitmap)
            //获取到检测结果
            val bboxes: List<TfliteRunner.Recognition> = detector.runInference()
            //绘制识别框到bitmap里
            val resBitmap: Bitmap =ImageProcess.drawBboxes(bboxes, bitmap, 640)
            if (bboxes.size>0){
                //对人点击
                if (bboxes[bboxes.lastIndex].title=="person"){
                    if (!personClick){
                        //检测到人之后对人进行点击
                        //ScreenUtil.click(bboxes[bboxes.lastIndex].location.centerX(), bboxes[bboxes.lastIndex].location.centerY())
                        personClick = true //防止重复点击
                    }
                }else{
                    personClick = false
                }
            }else{
                personClick = false
            }

            runOnUiThread {
                contentImageView?.apply {
                    setImageBitmap(resBitmap)
                }

            }
            close()
        }


    }

关键使用类

悬浮窗 -FloatUtil
模型检测-TfliteRunner
首页-MainActitvity
边框绘制-ImageProcess

使用效果

请添加图片描述

最后github地址
yolov5结合tensflow在移动端的方案

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

安卓利用tensorflow-lite使用yolov5训练的模型 的相关文章

  • Spring官方提供【CSRF攻击】解决方案

    步入正文 Cookie cookie是我们常见用来保存用户态信息 xff0c cookie跟随我们的请求自动携带 在同一域名下的请求 xff0c cookie总是自动携带 用户态 当前登入者的用户信息 以上的特性会导致一个潜在漏洞 CSRF
  • RocketMQ 一个topic 多个消费者只有一个消费的问题

    前言 很多时候 xff0c 我们会在多个地方同时订阅一个 topic xff0c 但是发现消费者只能执行一个后注册消费者会顶替之前注册的消费者 原因 在 subscribeTable 和 subscriptionInner 方法中 xff0
  • 如何快速学习一门新计算机语言

    本来想总结老师的方法的 xff0c 可在网上找到一篇一模一样的 xff0c 为了保证原创性 xff0c 所以只好直接引用啦 点击打开链接 如何快速学习一门新计算机语言
  • 福利抽奖 | 开源企业级监控Zabbix6.0都有哪些亮点

    Zabbix是企业级开源监控解决方案 xff0c 支持实时监控数万台服务器 虚拟机和网络设备 xff0c 采集百万级监控指标 xff0c 提供跨平台支持 Zabbix完全开源免费 xff0c 社区十分活跃 xff0c 生态建设良好 xff0
  • Git的一些常用概念

    git思维导图 Git工作区域 为了说明我们日常开发中执行的一系列Git命令的作用是什么 xff0c 我们需要了解Git的工作区域的概念 xff0c 几乎每一个常见的Git命令操作都可以通过工作区域来解释 Git本地有四个工作区域 xff1
  • 有没有完全自主的国产化数据库技术

    前段时间的俄乌冲突 xff0c Oracle 宣布 暂停在俄罗斯的所有业务 xff0c 相信大家的心情绝不是隔岸观火 xff0c 而是细思恐极 数据库号称 IT 领域三大核心之一 xff08 其他两个是 CPU 和操作系统 xff09 xf
  • 多个线程之间如何协同

    1 CountDownLatch 计数器 在多线程协作完成任务的时候 xff0c 有时候需要等待其他线程完成任务后 xff0c 主线程才能继续执行 xff0c 我们可以使用 Thread 类的 join 方法 xff0c 让主线程等待被 j
  • 利用Sharding-JDBC 实现Mysql读写分离

    为什么要读写分离 xff1f 读写分离则是将事务性的增 改 删操作在主库执行 xff0c 查询操作在从库执行 一般业务的写操作都是比较耗时 xff0c 为了避免写操作影响查询的效率 xff0c 可以使用读写分离 当然读写分离并不是万能的 x
  • 并发编程的核心问题

    并发编程并不是一项孤立存在的技术 xff0c 也不是脱离现实生活场景而提出的一项技术 相反 xff0c 并发编程是一项综合性的技术 xff0c 同时 xff0c 它与现实生活中 的场景有着紧密的联系 并发编程有三大核心问题 xff1a 分工
  • windows xp管理工具不见了怎么办

    管理工具其实是一个文件夹C ProgramData Microsoft Windows Start Menu Programs Administrative Tools 管理工具里的内容就是这个文件夹里的内容 xff0c 你的内容不见了 x
  • 分享搭建脚手架的一些经验

    印象中有些日子没有写文章了 xff0c 最近一直在放飞自我 xff0c 今天和大家分享的一些在搭建脚手架和编程中的一些实践原则 所有目标都是 清晰架构分层 使用统一的依赖管理 这种方式是基于我多年来的实践 最开始我也将项目类库及其版本随意的
  • POJO、Java Bean是如何定义的

    之前介绍过DTO PO VO的转换 xff0c 在日常开发中还有一些类经常被人叫做POJO xff0c 还有的人叫它们Java Bean 这些概念都是在特定场景下引入 xff0c 用来表明它们的特性的 那这些称呼都是啥意思 xff0c 有啥
  • Maven依赖的作用域你到底用对了没有

    Maven是目前Java开发主要使用的依赖管理构建工具之一 xff0c 但是很多人在引用依赖的时候直接引用坐标 xff0c 而没有考虑依赖的作用范围 xff0c 结果导致出现这样和那样的问题 今天胖哥就来说明一下Maven引用依赖的一个要点
  • 胖哥亲自带你玩转Spring Security OAuth2

    参与Spring Security与OAuth2专栏限定免费学习群 xff0c 请从活动主页扫描第三个专栏学习群二维码入群 xff01 关于21天学习挑战赛活动细节 xff0c 请从点击活动主页了解 作者介绍 码农小胖哥 xff0c Spr
  • 21天,胖哥亲自带你玩转OAuth2

    参与Spring Security与OAuth2专栏限定免费学习群 xff0c 请从阅读原文扫描第三个专栏学习群二维码入群 xff01 关于21天学习挑战赛活动细节 xff0c 请点击 阅读原文了解 作者介绍 码农小胖哥 xff0c Spr
  • StoneDB 为何敢称业界唯一开源的 MySQL 原生 HTAP 数据库?

    近些年 xff0c HTAP 正在受到人们越来越多的关注 xff0c Gartner 在 2014 年提出了 HTAP 这个术语和它的定义 xff1a Hybrid transaction analytical processing HTA
  • 聊聊数据库建表的15个小技巧

    前言 对于后端开发同学来说 xff0c 访问数据库 xff0c 是代码中必不可少的一个环节 系统中收集到用户的核心数据 xff0c 为了安全性 xff0c 我们一般会存储到数据库 xff0c 比如 xff1a mysql xff0c ora
  • 【收藏备用】15大超全应用场景总结,进阶主机安全

    随着业务数字化转型 xff0c 企业的业务变得越来越开放和灵活 xff0c 面临的安全挑战也日益增加 在这种多变 开放的场景下 xff0c 无论安全边界怎么做 xff0c 都无法阻挡黑客打破边界进入企业内部来窃取核心资产 当下安全对抗以及安
  • Java 19 正式发布,改善多线程、并发编程难度

    Java 19 在数分钟前正式发布 xff0c 这是一个非 LTS xff08 长期支持 xff09 版本 该版本的七项功能包括结构化并发 记录模式 外部函数和内存 API 的预览 xff0c 以及对开源 Linux RISC V 指令集架
  • 文末下载方式 | Jetbrains的下一代IDE工具Fleet公测

    之前胖哥介绍了Jetbrains的下一代IDE工具Fleet xff0c 激起了很多同学的兴趣 如果你还不知道Fleet是什么就去看下这一篇文章 Fleet是Jetbrains新出品的一款分布式多语言编辑器和 IDE 它是 IntelliJ

随机推荐