人脸姿态估计浅谈~

之前做过一段时间的人脸姿态估计研究,取得了比较理想的效果,拿出来和大家分享一下,第一次写博客,肯定有表达不清晰的地方,还请大家多多批评哈!

当时自己刚开始这方面的研究,特别想找到关于这方面的博客介绍,可惜没有,于是产生了写一篇该方向上博客的想法,废话不多说,开始介绍!

人脸姿态估计,顾名思义,给定一张人脸图像,确定其姿态,姿态由什么构成呢?很简单(pitch,yaw,roll)三种角度,分别代表上下翻转,左右翻转,平面内旋转的角度。



目前,人脸姿态估计有多种方法,可以分为基于模型的方法,基于表观的方法,基于分类的方法。我之前做过 这方面的调研,调研的结果很明显,基于模型的方法得到的效果最好,因为其得到的人脸姿态是连续的,而另外两种,是离散的,并且很耗时间。

人脸姿态估计算法一般当做很多人脸对齐相关论文的副产品被提出,近期,比较“出名”的人脸对齐论文主要来自于CVPR,ICCV等,如下:

《Supervised Descent Method and its Applications to Face Alignment》,这篇论文提供了demo,并且附加了人脸姿态估计功能,估计精度还不错。

《Face Alignment at 3000 FPS via Regressing Local Binary Features》,这篇文章是最新的人脸对齐算法,基于随机森林的算法,速度比较快,精度基本和上一篇持平。

《Face Alignment by Explicit Shape Regression》这篇文章很出名,作者也和上一篇是同一人。

还有经典的人脸对齐鼻祖算法ASM,AAM,想必大家也都知道,这里不再多说,因为咱这篇博客的主题是人脸姿态估计嘛!~

基于模型的估计方法的前提是,手头必须具备两样东西,一个是人脸特征点(眼镜,嘴巴,鼻子等处的像素位置),另外一个,是需要自己制作一个3维的,正面的“标准模型”。


这个模型的好坏很重要,人脸的特征点精度可以不高,因为后面的姿态估计算法可以采用鲁棒方法予以弥补,但是标准模型一旦有问题,势必会导致姿态估计的精度偏低。

算法最重要的还是思想,其余诸如流程什么的,都是实现思想的手段而已。人脸姿态估计的思想:旋转三维标准模型一定角度,直到模型上“三维特征点”的“2维投影”,与待测试图像上的特征点(图像上的特征点显然是2维)尽量重合。这时候我们脑海中就应该浮现出一种诡异的场景:在幽暗的灯光中,一个发着淡蓝色光芒的人皮面具一点点的“自我调整”,突然一下子“完美无缺”的“扣在了你的脸上”。这就是人脸姿态估计的思想

想到了什么没?这貌似听起来像是某种数学中常常介绍的一种方法。是的,大部分论文中也经常利用这种方式来建立模型。这个方法就叫做“非线性最小二乘”。

我们也可以利用非线性最小二乘方法来建立我们的模型,模型公式如下:


其中,(α,β,γ)代表人脸姿态三个旋转角度, N代表着一张人脸上标定特征点的个数,qi代表着待测试人脸特征点,pi代表对应着的三维通用标准模型特征点,R代表旋转矩阵, t为空间偏移向量,s为伸缩因子。R的具体形式是如下三个矩阵相乘:


给出了人脸姿态估计的模型,我们可以发现,这个公式的形式,刚好对应于刚刚提出的人脸姿态估计算法思想。数学是奇妙的!

更奇妙的在下面.....

这个公式看起来很直观,很好的解释了人脸姿态估计的内涵,但是,这个公式怎么求解?

对了,别忘记,这是“烂大街的”非线性最小二乘算法,从牛顿爷爷开始,就有着大把的优化方法,梯度下降,牛顿高斯,信赖域,马夸尔特等等等等等用于解决它,等到下一篇博客,我会尽量用通俗的语言,为大家介绍姿态估计的下一个重要阶段:迭代求精。


附图(姿态估计效果图):

    

                      原图                                       3D标准模型正面照                         姿态估计算法拟合图

 

  • 21
    点赞
  • 82
    收藏
    觉得还不错? 一键收藏
  • 14
    评论
以下是OpenMV4的人脸姿态估计代码: 首先,我们需要导入所需的库和模块: ```python import sensor, image, time import KPU as kpu import lcd from fpioa_manager import * from machine import I2C from board import board_info from fpioa_manager import * from pmu import axp192 from modules import ws2812 ``` 然后,我们需要初始化硬件和模块: ```python fm.register(board_info.LED_W, fm.fpioa.GPIO0) led = GPIO(GPIO.GPIO0, GPIO.OUT) led.value(1) lcd.init(freq=15000000) lcd.direction(lcd.YX_RLDU) sensor.reset() sensor.set_pixformat(sensor.RGB565) sensor.set_framesize(sensor.QVGA) sensor.set_vflip(1) sensor.run(1) kpu.memtest() task = kpu.load(0x200000) ``` 接下来,我们需要创建I2C总线和AXP192电源管理器的实例: ```python fm.register(20, fm.fpioa.GPIOH7) fm.register(21, fm.fpioa.GPIOH6) i2c = I2C(I2C.I2C0, freq=400000, scl=21, sda=20) pmu = axp192(i2c=i2c) pmu.enablePMICSleepMode(True) ``` 然后,我们需要定义一些变量和函数: ```python def draw_string_at(img, x, y, text): img.draw_string(x, y, text, color=(255, 255, 255), scale=2) colors = [(255, 0, 0), (255, 128, 0), (255, 255, 0), (128, 255, 0), (0, 255, 0), (0, 255, 128), (0, 255, 255), (0, 128, 255), (0, 0, 255), (128, 0, 255), (255, 0, 255), (255, 0, 128), (128, 128, 128), (0, 0, 0)] def draw_arrow(img, x, y, dx, dy): img.draw_line(x, y, x+dx, y+dy, color=(255, 0, 0), thickness=3) img.draw_circle(x+dx, y+dy, 5, color=(255, 0, 0), thickness=3) def get_pose_string(pose): return "Yaw: {:.2f}, Pitch: {:.2f}, Roll: {:.2f}".format(pose[0], pose[1], pose[2]) ``` 最后,我们可以开始循环读取图像,进行人脸检测和姿态估计,并在LCD屏幕上显示结果: ```python while True: img = sensor.snapshot() boxes = img.detect_face() if boxes: for box in boxes: x, y, w, h = box img.draw_rectangle(x, y, w, h, color=colors[0], thickness=3) face_img = img.crop(x, y, w, h) resized_img = face_img.resize(128, 128) out = kpu.forward(task, resized_img) pose = out[:3] draw_string_at(img, x, y-30, get_pose_string(pose)) draw_arrow(img, int(x+w/2), int(y+h/2), int(pose[0]*50), int(pose[1]*50)) lcd.display(img) ``` 完整代码如下:

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 14
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值