草庐IT

HeadPose Estimation头部姿态估计头部朝向(Android)

AI吃大瓜 2023-09-11 原文

HeadPose Estimation头部姿态估计头部朝向(Android)

目录

HeadPose Estimation头部姿态估计头部朝向(Android)

0.前言

1.HeadPose

2.pitch、yaw、roll三个角的区别

3.头部姿态估计评价指标

4.头部姿态估计数据

5.FSA-Net介绍

6. 头部姿态估计效果展示

7. 头部姿态估计Android源码下载


0.前言

本篇,将介绍一种基于深度学习的头部姿态估计模型FSA-Net。鄙人已经复现论文的结果,并对FSA-Net进行了轻量化,以便在移动端可以跑起来;目前Android Demo已经集成人脸检测和头部朝向模型,在普通手机可实时检测(30ms左右),CPU支持多线程处理,GPU支持OpenCL加速处理,先看一下效果哈:

尊重原创,转载请注明出处】:HeadPose Estimation头部姿态估计头部朝向(Android)_pan_jinquan的博客-CSDN博客

 CPU-4线程GPU

Android Demo支持的特性主要如下: 

  • 支持人脸检测:已经集成了轻量化的人脸检测,在普通手机只需要15ms左右,持CPU多线程处理,GPU支持OpenCL加速处理
  • 支持头部姿态估计:已经集成了轻量化的头部姿态估计,在普通手机只需要7ms左右,持CPU多线程处理,GPU支持OpenCL加速处理
  • 支持多人头部姿态估计
  • Demo支持图片,视频,摄像头等多种方式输入数据
  • 整个过程在普通手机可实时检测,30ms左右

1.HeadPose

头部姿态估计(Head Pose Estimation ),也称头部朝向估计,主要是获得脸部朝向的角度信息,即欧拉角(pitch,yaw,roll)表示。

头部姿态估计方法很多,主要可以分为两大类

(1)基于PNP的头部姿态估计方法

使用透视变换可以完成2D到3D的转换,可以简单的想象为将照片上的人脸图像按照一定的角度进行多点拉扯形成3D图像,然后根据角度来判断姿态。使用的方法原理为使用2D平面上人脸的特征点和3D空间内对应的坐标点,按照求解pnp问题的思路。找到一个映射关系,从而估计头部的姿态。

经典的 Head Pose Estimation 算法的步骤一般为:

  1. 2D人脸关键点检测;
  2. 3D人脸模型匹配;
  3. 求解3D点和对应2D点的转换关系;
  4. 根据旋转矩阵求解欧拉角。

基于PNP的头部姿态估计是比较传统的算法,其效果比较依赖人脸关键点检测,实际测试误差还是比较大。

可参考资料:基于3D通用模型的头部姿态估计_一半糊涂、的博客-CSDN博客_头部姿态估计

(2)基于深度学习的方法 

基于深度学习的方法,把脸部朝向的角度信息,即欧拉角(pitch,yaw,roll)当作一个多任务的回归模型(也可以转为分类)。其模型输入一张RGB人脸图像,输出三个值,代表头部朝向的欧拉角,(pitch,yaw,roll)。相比传统的头部姿态估计算法,该方法不依赖于人脸关键点,精度更高效果更好。

比如论文《Fine-Grained Head Pose Estimation Without Keypoints》就是这么简单粗暴:

论文地址:https://arxiv.org/abs/1710.00925v2
代码链接:https://github.com/natanielruiz/deep-head-pose

当然,还有FSA-Net,本博客就是在FSA-Net的基础上进行优化

参考资料:FSA-Net学习笔记_南风不竞:的博客-CSDN博客


2.pitch、yaw、roll三个角的区别

欧拉角(pitch,yaw,roll)遵循三维空间右手笛卡尔坐标原则:

蓝色的代表滚转角 (roll),绿色的代表偏航角(yaw),红色的代表俯仰角(pitch)

欧拉角说明图示
pitch俯仰角,将物体绕X轴旋转(localRotationX),即点头 上负下正
yaw偏航角,将物体绕Y轴旋转(localRotationY),即摇头 左正右负
roll滚转角,将物体绕Z轴旋转(localRotationZ), 即转头(歪头)左负右正

3.头部姿态估计评价指标

头部姿态估计主要有两种评价准则

(1)平均绝对误差(MAE)

(2)平均精度


4.头部姿态估计数据

数据集说明
AFLW2000
BIWI
  • 数据集包含20人的超过15,000张图像(6位女性和14位男性-两次记录了4个人)。
  • 对于每一帧,都提供深度图像,相应的rgb图像(均为640x480像素)和注释。
  • 头部姿势范围涵盖大约+ -75度偏航和+ -60度俯仰。
  • 地面真相以头部的3D位置及其旋转的形式提供
  • 下载地址:https://data.vision.ee.ethz.ch/cvl/gfanelli/head_pose/head_forest.html


5.FSA-Net介绍

FSA-Net 是2019年CVPR中的一篇文章,下面是FSA-NET模型架构图:

首先,输入的图片经过两条流(two Stream)。两条流在3个stage各自提取一个特征图。相同stage提取出的特征图经过fusion module(图中的绿色框)。

原文:fusion module 首先将每个stage的两个feature map,通过element-wise multiplication得到combined feature map。然后通过c 1x1 的卷积将特征图变成c个channel。最后,用平均池化将特征图变成 w*h,最终,我们得到k个stage的特征图Uk  .如上图的 U1-Uk.

得到了K个大小为  特征图后,聚合模块的任务就是将其聚合为一个更小的更representative的特征图,具体来说就是将特征图精简为  。已有的一些方法如capsule 和NetVLAD没有关注空间之间的相对信息。所以在进入特征聚合模块前,先进行空间聚合(spatial grouping)

GitHub - shamangary/FSA-Net: [CVPR19] FSA-Net: Learning Fine-Grained Structure Aggregation for Head Pose Estimation from a Single Image


6. 头部姿态估计

目前Android Demo已经集成人脸检测头部朝向模型,支持以下功能:

  • 支持人脸检测:已经集成了轻量化的人脸检测,在普通手机只需要15ms左右,持CPU多线程处理,GPU支持OpenCL加速处理
  • 支持头部姿态估计:已经集成了轻量化的头部姿态估计,在普通手机只需要7ms左右,持CPU多线程处理,GPU支持OpenCL加速处理
  • 支持多人头部姿态估计
  • Demo支持图片,视频,摄像头等多种方式输入数据
  • 整个过程在普通手机可实时检测,30ms左右

算法核心代码,都采用C++实现,这是JNI部分,也是接口的核心代码:

package com.cv.tnn.model;

import android.graphics.Bitmap;

public class Detector {

    static {
        System.loadLibrary("tnn_wrapper");
    }


    /***
     * 初始化关键点检测模型
     * @param face_model: 人脸检测模型(不含后缀名)
     * @param head_model: 头部朝向模型(不含后缀名)
     * @param root:模型文件的根目录,放在assets文件夹下
     * @param model_type:模型类型
     * @param num_thread:开启线程数
     * @param useGPU:关键点的置信度,小于值的坐标会置-1
     */
    public static native void init(String face_model,String head_model, String root, int model_type, int num_thread, boolean useGPU);

    /***
     * 检测关键点
     * @param bitmap 图像(bitmap),ARGB_8888格式
     * @param score_thresh:置信度阈值
     * @param iou_thresh:  IOU阈值
	 * @param dst_bitmap图像(bitmap),头部姿态估计可视化效果图
     * @return
     */
    public static native FrameInfo[] detect(Bitmap bitmap, float score_thresh, float iou_thresh,Bitmap dst_bitmap);
}

Android源码的头部朝向坐标绘制,我是使用的OpenCV绘制实现的,然后把绘制好Bitmap图像通过JNI映射到上层,并进行显示,核心显示代码如下:

/***
 * 绘制yaw,pitch,roll坐标轴(左手坐标系)
 * @param imgBRG 输入必须是BGR格式的图像
 * @param pitch红色X
 * @param yaw 绿色Y
 * @param roll 蓝色Z
 * @param center 坐标原始点
 * @param vis
 * @param size
 */
void draw_yaw_pitch_roll_in_left_axis(cv::Mat &imgBRG, float pitch, float yaw, float roll,
                                      cv::Point center, int size, int thickness, bool vis) {

    float cx = center.x;
    float cy = center.y;
    char text[200];
    sprintf(text, "(pitch,yaw,roll)=(%3.1f,%3.1f,%3.1f)", pitch, yaw, roll);
    pitch = pitch * PI / 180;
    yaw = -yaw * PI / 180;
    roll = roll * PI / 180;
    // X-Axis pointing to right. drawn in red
    float x1 = size * (cos(yaw) * cos(roll)) + cx;
    float y1 = size * (cos(pitch) * sin(roll) + cos(roll) * sin(pitch) * sin(yaw)) + cy;
    cv::Scalar color_yaw_x(0, 0, 255); //BGR;
    // Y-Axis | drawn in green
    float x2 = size * (-cos(yaw) * sin(roll)) + cx;
    float y2 = size * (cos(pitch) * cos(roll) - sin(pitch) * sin(yaw) * sin(roll)) + cy;
    cv::Scalar color_pitch_y(0, 255, 0);
    // Z-Axis (out of the screen) drawn in blue
    float x3 = size * (sin(yaw)) + cx;
    float y3 = size * (-cos(yaw) * sin(pitch)) + cy;
    cv::Scalar color_roll_z(255, 0, 0);
    float tipLength = 0.2;
    cv::arrowedLine(imgBRG, cv::Point(int(cx), int(cy)), cv::Point(int(x1), int(y1)), color_yaw_x,
                    thickness,
                    tipLength);
    cv::arrowedLine(imgBRG, cv::Point(int(cx), int(cy)), cv::Point(int(x2), int(y2)), color_pitch_y,
                    thickness,
                    tipLength);
    cv::arrowedLine(imgBRG, cv::Point(int(cx), int(cy)), cv::Point(int(x3), int(y3)), color_roll_z,
                    thickness,
                    tipLength);
    if (vis) {
        cv::putText(imgBRG,
                    text,
                    cv::Point(cx, cy),
                    cv::FONT_HERSHEY_COMPLEX,
                    0.5,
                    (0, 0, 255));
    }
}

一些Android测试测试效果:https://panjinquan.blog.csdn.net/article/details/124943419

Android效果图 CPU-4线程GPU

一些图片测试效果:

一些异常错误解决方法:运行APP闪退:dlopen failed: library "libomp.so" not found

参考解决方法:解决dlopen failed: library “libomp.so“ not found_PKing666666的博客-CSDN博客_dlopen failed


7. 头部姿态估计Android源码下载

有关HeadPose Estimation头部姿态估计头部朝向(Android)的更多相关文章

  1. 安卓apk修改(Android反编译apk) - 2

    最近因为项目需要,需要将Android手机系统自带的某个系统软件反编译并更改里面某个资源,并重新打包,签名生成新的自定义的apk,下面我来介绍一下我的实现过程。APK修改,分为以下几步:反编译解包,修改,重打包,修改签名等步骤。安卓apk修改准备工作1.系统配置好JavaJDK环境变量2.需要root权限的手机(针对系统自带apk,其他软件免root)3.Auto-Sign签名工具4.apktool工具安卓apk修改开始反编译本文拿Android系统里面的Settings.apk做demo,具体如何将apk获取出来在此就不过多介绍了,直接进入主题:按键win+R输入cmd,打开命令窗口,并将路

  2. 欧拉角表示的姿态矩阵(313和312转序) - 2

    一、习惯约定图片来自PSINS(高精度捷联惯导算法)PSINS工具箱入门与详解.pptx二、基本旋转矩阵绕x轴逆时钟旋转α\alphaα角度Rx(α)=[ 1000cos⁡αsin⁡α0−sin⁡αcos⁡α]R_x(\alpha)=\begin{bmatrix}\1&0&0\\0&\cos\alpha&\sin\alpha\\0&-\sin\alpha&\cos\alpha\end{bmatrix}Rx​(α)=​ 100​0cosα−sinα​0sinαcosα​​绕y轴逆时钟旋转α\alphaα角度Ry(α)=[ cos⁡α0−sin⁡α010sin⁡α0cos⁡α]R_y(\alpha

  3. Android Studio开发之使用内容组件Content获取通讯信息讲解及实战(附源码 包括添加手机联系人和发短信) - 2

    运行有问题或需要源码请点赞关注收藏后评论区留言一、利用ContentResolver读写联系人在实际开发中,普通App很少会开放数据接口给其他应用访问。内容组件能够派上用场的情况往往是App想要访问系统应用的通讯数据,比如查看联系人,短信,通话记录等等,以及对这些通讯数据及逆行增删改查。首先要给AndroidMaifest.xml中添加响应的权限配置 下面是往手机通讯录添加联系人信息的例子效果如下分成三个步骤先查出联系人的基本信息,然后查询联系人号码,再查询联系人邮箱代码 ContactAddActivity类packagecom.example.chapter07;importandroid

  4. Android 10.0 设置默认launcher后安装另外launcher后默认Launcher失效的功能修复 - 2

    1.前言 在10.0的系统rom定制化开发中,在系统中有多个launcher的时候,会在开机进入launcher的时候弹窗launcher列表,让用户选择进入哪个launcher,这样显得特别的不方便所以产品开发中,要求用RoleManager的相关api来设置默认Launcher,但是在设置完默认Launcher以后,在安装一款Launcher的时候,默认Launcher就会失效,在系统设置的默认应用中Launcher选项就为空,点击home键的时候会弹出默认Launcher列表,让选择进入哪个默认Launcher.所以需要从安装Launcher的流程来分析相关的设置。来解决问题设置默认La

  5. AiBote 2022 新研发的自动化框架,支持 Android 和 Windows 系统。速度非常快 - 2

    Ai-Bot基于流行的Node.js和JavaScript语言的一款新自动化框架,支持Windows和Android自动化。1、Windowsxpath元素定位算法支持支持Windows应用、.NET、WPF、Qt、Java和Electron客户端程序和ie、edgechrome浏览器2、Android支持原生APP和H5界面,元素定位速度是appium十倍,无线远程自动化操作多台安卓设备3、基于opencv图色算法,支持找图和多点找色,1080*2340全分辨率找图50MS以内4、内置免费OCR人工智能技术,无限制获取图片文字和找字功能。5、框架协议开源,除官方node.jsSDK外,用户可

  6. Android Gradle 7.1+新版本依赖变化 - 2

    前一段时间由于工作需要把可爱的小雪狐舍弃了,找到了小蜜蜂。但是新版本的小蜜蜂出现了很多和旧版本不一样的位置。1.功能位置迁移,原来在工程build.gradle的buildscript和allprojects移动至setting.gradle并改名为pluginManagement和dependencyResolutionManagement。里面的东西依旧可以按照原来的copy过来。pluginManagement{repositories{gradlePluginPortal()google()mavenCentral()}}dependencyResolutionManagement{r

  7. ruby - Ruboto 的最佳教程(适用于 Android 的 ruby​​)? - 2

    关闭。这个问题不符合StackOverflowguidelines.它目前不接受答案。要求我们推荐或查找工具、库或最喜欢的场外资源的问题对于StackOverflow来说是偏离主题的,因为它们往往会吸引自以为是的答案和垃圾邮件。相反,describetheproblem以及迄今为止为解决该问题所做的工作。关闭9年前。Improvethisquestion我几乎用完了Ruby,但现在想试试Ruboto,android上的ruby​​。谷歌未能给我足够的(几乎没有结果)。所以任何人都可以分享一些关于Ruboto的教程。

  8. Android Studio 解决Could not resolve com.android.tools.build:gradle:7.4.2问题 - 2

    Aproblemoccurredconfiguringrootproject'MyApplication2'.>Couldnotresolveallfilesforconfiguration':classpath'.  >Couldnotresolvecom.android.tools.build:gradle:7.4.2.   Requiredby:     project:>com.android.application:com.android.application.gradle.plugin:7.4.2     project:>com.android.library:com.andr

  9. Android对话框的详细介绍(提示对话框,自定义对话框) - 2

    简介:我们都知道在Android开发中,当我们的程序在与用户交互时,用户会得到一定的反馈,其中以对话框的形式的反馈还是比较常见的,接下来我们来介绍几种常见的对话框的基本使用。前置准备:(文章最后附有所有代码)我们首先先写一个简单的页面用于测试这几种Dialog(对话框)代码如下,比较简单,就不做解释了一、提示对话框(即最普通的对话框)首先我们给普通对话框的按钮设置一个点击事件,然后通过AlertDialog.Builder来构造一个对象,为什么不直接Dialog一个对象,是因为Dialog是一个基类,我们尽量要使用它的子类来进行实例化对象,在实例化对象的时候,需要将当前的上下文传过去,因为我这

  10. android 多屏幕显示activity,副屏,无线投屏 - 2

    目录1.首先,需要一个副屏1.1可以通过代码的形式自己创建VirtualDispaly,创建副屏。1.2或者,在手机的开发者模式中直接开启模拟副屏,也是可以的。2.0怎么利用这个副屏幕?2.1 用作presentation演示ppt:2.2克隆主屏幕的内容,就是主屏幕显示什么,副屏显示同样的内容,镜像模式。2.3 将一个activity从第二个屏幕上启动,作为一个独立的屏幕首先说明一下这个多屏幕的概念,这里不是指分屏显示。分屏显示:是一个屏幕分出多个窗口,分别显示不同app.多屏支持:是一个设备有多个屏幕,怎么让不同的屏幕显示不同的app,或者是一个app同时用两个屏幕来显示不同的页面内容。多

随机推荐