安卓利用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训练的模型 的相关文章

  • js获取整个页面源码

    通过 outerHTML document documentElement outerHTML 通过异步请求 get window location href function res console log res 通过jQuery 34
  • 查看自己电脑被别人U盘拷贝文件

    windows 43 R reg query HKLM System currentcontrolset enum usbstor s gt c usb txt FriendlyName 第二种是使用USBViewer USBViewer
  • 普罗米修斯-docker安装

    1 只有一台服务器 xff0c 所以使用docker来进行试验 安装docker curl fsSL https get docker com bash s docker mirror Aliyun 查看安装版本 docker versio
  • netty参数设置

    1 通用参数 CONNECT TIMEOUT MILLIS Netty参数 xff0c 连接超时毫秒数 xff0c 默认值30000毫秒即30秒 MAX MESSAGES PER READ Netty参数 xff0c 一次Loop读取的最大
  • git 删除远程文件目录

    git rm r cached 文件夹名称 git add git commit m 34 aa 34 git push origin master
  • git删除远程分支

    branch 1 列出分支 xff0c a参数是列出所有分支 xff0c 包括远程分支 git branch a 2 创建一个本地分支 git branch branchname 3 创建一个分支 xff0c 并切换到该分支 git che
  • maven命令上传第三方包

    mvn deploy deploy file Dmaven test skip 61 true DgroupId 61 sdk的groupId DartifactId 61 包的名称 Dversion 61 版本号 如 xff1a 0 0
  • 解决图片上传权限问题

    linux默认umask为022 xff0c 对应权限为755 xff0c 其它用户可读可执行 可以vim etc profile xff0c 搜索umusk关键字查看 if UID gt 199 amp amp 34 96 usr bin
  • 微信小程序 解决 wx.request同步问题 方便开发 Promise方式

  • Python经典书籍有哪些?这份书单送给你_黑马程序员

    文章目录 一 Python 基础 01 Python编程 xff1a 从入门到实践 xff08 第2版 xff09 02 Python编程快速上手 xff08 第2版 xff09 03 Python编程初学者指南 04 笨方法 学Pytho
  • 记忆的方法

    1 第一招 xff0c 在背书的时候 xff0c 用双手捂住你的耳朵 xff0c 并且大声的朗读 研究表明 xff0c 用手捂着耳朵来朗读的话 xff0c 声音是直接通过骨骼来传输到内耳 xff0c 对大脑刺激会更加强烈 xff0c 记忆也
  • ssh登录服务器缓慢问题

    问题描述 问题刚开始是由pod启动失败 xff0c 报错unable to ensure pod container exists failed to create container for kubepods burstable pod8
  • UCOSIII学习-任务管理

    UCOSIII学习 任务管理 1 UCOSIII 任务组成2 UCOSIII 默认系统任务3 UCOSIII 任务状态4 任务堆栈1 任务堆栈的创建2 任务堆栈初始化 5 任务控制块1 任务控制块创建2 任务控制块初始化 6 任务就绪表1
  • ubuntu(Linux)配置允许远程登陆

    安装ubuntu后默认不可以以root方式登录系统 xff0c 需要做以下配置 1 使用sudo i 命令可以让用户切换到root用户 xff0c guo用户是安装ubuntu时配置的用户 xff0c 因人而异 xff1b 2 配置root
  • python带下划线的变量和函数

    参考文献 xff1a https blog csdn net AI S YE article details 44685139
  • ADD,COPY,ENTRYPOINT和cmd

    Dockerfile中有关信息 xff1a ADD与COPY区别 add 1 对压缩包进行解压2 可以在后面直接跟文件地址 copy xff1a 把本地的文件copy到容器里面 ENTRYPOINT与CMD区别 1 第一种解释 xff08
  • docker实例操作

    很多东西都是借鉴各位大神的 xff0c 也不知道具体是谁或是哪个链接 xff0c 很抱歉 两者同为目前版本中个人和小团队常用的服务级操作系统 xff0c 在线提供的软件库中可以很方便的安装到很多开源的软件及库 两者都使用bash作为基础sh
  • 三、FreeRTOS任务管理--常用函数

    任务的基本概念 FreeRTOS 的任务可认为是一系列独立任务的集合 每个任务在自己的环境中运行 在任何时刻 xff0c 只有一个任务得到运行 xff0c FreeRTOS 调度器决定运行哪个任务 调度器会不断的启动 停止每一个任务 xff
  • 七、FreeRTOS事件和常用函数接口

    基本概念 事件是一种实现任务间通信的机制 xff0c 主要用于实现多任务间的同步 xff0c 但事件通信只能是事件类型的通信 xff0c 无数据传输 与信号量不同的是 xff0c 它可以实现一对多 xff0c 多对多的同步 即一个任务可以等
  • PX4姿态估计源码分析

    写在前面 今天入坑PX4开始学习PX4代码 xff0c pixhawk硬件是可以支持PX4 ardupilot两套固件 我用的是1 6 0rc1版本代码 代码位置 xff1a Firmware1 6 0rc1 src modules att

随机推荐