人脸对齐 3000fps

2023-10-21 16:50
文章标签 对齐 人脸 3000fps

本文主要是介绍人脸对齐 3000fps,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

1 介绍

          3000fps 相关概念主要是在实现jda方法的时候仔细了解过,基本原理总体说来很复杂,但是从实现的角度来看并不难。该方法的速度还是不错的,能够达到论文中提到的数据,效果嘛就有点差强人意了,主要还是由样本决定。

2 方法

       总体上,人脸对齐的主要理论依据是如下方程:

                                    F * W = R

其中F是特征,W是转换系数,R是偏移量。

2.1 基础知识

       本节主要介绍两个知识:相似变换(similiarity transform)和均值人脸(meanshape)。

2.1.1 相似变换

        相似变换的目的是求解两个形状之间的尺度和角度关系,和普氏分析的作用相同,不同点是不需要迭代求解,普氏分析理论上更准确,实际上在这里没什么特殊效果。下面的代码(取自:https://github.com/yulequan/face-alignment-in-3000fps/blob/master/Utils.cpp)就是相似变换的过程:

 

void SimilarityTransform(const Mat_<double>& shape1, const Mat_<double>& shape2, Mat_<double>& rotation,double& scale){rotation = Mat::zeros(2,2,CV_64FC1);scale = 0;// center the datadouble center_x_1 = 0;double center_y_1 = 0;double center_x_2 = 0;double center_y_2 = 0;for(int i = 0;i < shape1.rows;i++){center_x_1 += shape1(i,0);center_y_1 += shape1(i,1);center_x_2 += shape2(i,0);center_y_2 += shape2(i,1); }center_x_1 /= shape1.rows;center_y_1 /= shape1.rows;center_x_2 /= shape2.rows;center_y_2 /= shape2.rows;Mat_<double> temp1 = shape1.clone();Mat_<double> temp2 = shape2.clone();for(int i = 0;i < shape1.rows;i++){temp1(i,0) -= center_x_1;temp1(i,1) -= center_y_1;temp2(i,0) -= center_x_2;temp2(i,1) -= center_y_2;}Mat_<double> covariance1, covariance2;Mat_<double> mean1,mean2;// calculate covariance matrixcalcCovarMatrix(temp1,covariance1,mean1,CV_COVAR_COLS);calcCovarMatrix(temp2,covariance2,mean2,CV_COVAR_COLS);double s1 = sqrt(norm(covariance1));double s2 = sqrt(norm(covariance2));scale = s1 / s2; temp1 = 1.0 / s1 * temp1;temp2 = 1.0 / s2 * temp2;double num = 0;double den = 0;for(int i = 0;i < shape1.rows;i++){num = num + temp1(i,1) * temp2(i,0) - temp1(i,0) * temp2(i,1);den = den + temp1(i,0) * temp2(i,0) + temp1(i,1) * temp2(i,1);      }double norm = sqrt(num*num + den*den);    double sin_theta = num / norm;double cos_theta = den / norm;rotation(0,0) = cos_theta;rotation(0,1) = -sin_theta;rotation(1,0) = sin_theta;rotation(1,1) = cos_theta;
}


文字描述是这样的:

 

       1)中心化两个形状;

       2)以质心为原点,计算其到没一个形状点之间的距离,并求和

       3)两个形状的尺度系数为2)中计算得到值的比值

       4)以质心为原点,计算其到每一个形状点之间的向量,并求解两个形状对应向量之间的角度

       5)两个形状之间的角度即4)得到角度的平均值

 

2.1.2 均值人脸

          对齐的过程是迭代进行基于估计人脸提取特征,然后预测偏移量,最后对估计人脸变形得到新的估计人脸,估计人脸的初值即均值人脸,均值人脸需要根据样本统计生成。有两种生成方法:

         1 平均形状:输入为大量人脸形状数据,人脸标准大小

         1)对每一一张人脸形状,计算外接矩形,以最长边和人脸标准大小之间的比例缩放人脸形状

         2)对1)中生成的人脸求平均值,即得到均值人脸

         2 迭代求解:输入为大量的人脸形状,人脸标准大:

 

         1)对每一张人脸形状,计算外接矩形,以最长边和人脸标准大小之间的比例缩放人脸形状

         2)对1)中生成的人脸求平均值,得到均值人脸

         3)将输入人脸通过相似变换使得其和均值人脸角度和尺度统一

         4)将3)中的到的形状求平均得到新的均值人脸

         5)重复3),4)使得前后的均值人脸误差小于指定值(L2范数),即收敛状态

2.2  特征提取

       3000fps 中用于回归的特征设计的非常巧妙,使得对齐的速度非常的快。特征提取是基于样本偏移量聚类方式计算得来的。聚类方式主要是通过决策树(cart),决策树分叉方法是基于shape index feature(形状索引特征)分类。

2.2.1 特征模板

         特征模板包含的元素:

         1)形状点ID1,

         2)基于ID1的偏移量dx1,dy1,

         3)形状点ID2,

         4)基于ID2的便宜量dx2,dy2。

        对于每一棵决策数的没一个结点都要随机生成指定数量的特征模板,然后从中根据指定原则选出最佳的那一个。偏移量的范围是以形状点为中心,指定半径内点与中心的插值。论文中叙述每一层的半径相对于前一层的半径要减小。
 

2.2.2 形状索引特征

       在对齐的过程中特征是基于当前形状提取的,为了能够提取特征统一,所以有了形状索引特征,主要是保证,假如特征模板指的是在人眼上方某处的点,对于不同角度不同尺度的人脸形状应该也是从同样的位置上获取像素。形状索引特征的提取方式如下:

       1)计算当前形状与均值形状之间的角度和尺度

       2)根据1)中的值使当前形状和均值形状角度和尺度统一

       3)2)中得到的形状加上对应偏移量

       4) 3)中得到的形状根据1)中的角度和尺度进行恢复

       5)根据4)中得到的形状提取制定像素值

       根据几何关系可以将偏移量根据1)中得到的角度和尺度进行变化,然后加到当前形状上,这样做更省时。

       shape index feature,就是基于人脸形状的几何关系求解两个像素点之差。

 

2.2.2 决策树

       决策数是cart树,是一个完全二叉树,深度至少为4,越高的树需要的样本量越大。

       决策树的节点保存有回归器,回归器是一种在形状索引特征的基础上保证样本指定形状点的偏移量(真实形状和估计形状之间的差值,形状要归一化到均值形状计算)方差最小,用于将偏移量相近的样本分为同一类。下面就是寻找最佳特征的代码,不过总觉得哪里写的有点问题,但是在我的框架内比开源的方法效果好:

 

static void binary_classify_loss(float *posFeats, float *offsets, int size, float &bestThresh, double &minLoss){float maxFeatValue, minFeatValue;float featStep, rfeatStep;double v2[LENGTH];double v[LENGTH];int count[LENGTH];maxFeatValue = -FLT_MAX, minFeatValue = FLT_MAX;for(int i = 0; i < size; i++){maxFeatValue = HU_MAX(maxFeatValue, posFeats[i]);minFeatValue = HU_MIN(minFeatValue, posFeats[i]);}featStep = (maxFeatValue - minFeatValue) / (LENGTH - 1);assert(featStep > 0);memset(v2, 0, sizeof(double) * LENGTH);memset(v, 0, sizeof(double) * LENGTH);memset(count, 0, sizeof(int) * LENGTH);rfeatStep = 1.0f / featStep;for(int i = 0; i < size; i++){int idx = (posFeats[i] -  minFeatValue) * rfeatStep;float off = offsets[i];v2[idx] += off * off;v[idx] += off;count[idx] ++ ;}for(int i = 1; i < LENGTH; i++){v2[i] += v2[i - 1];v[i] += v[i - 1];count[i] += count[i - 1];}double cumv2 = v2[LENGTH - 1];double cumv = v[LENGTH - 1];double cumc = size;for(int i = 0; i < LENGTH; i++){double lv2 = v2[i];double lv = v[i];int lc = count[i];double rv2 = cumv2 - lv2;double rv = cumv - lv;int rc = cumc - lc;double t, lvar, rvar, var;t = lv / lc;lvar = lv2 / lc - t * t;t = rv / rc;rvar = rv2 / rc - t * t;var = HU_MAX(lvar, rvar);if(var < minLoss){minLoss = var;bestThresh = i * featStep + minFeatValue;}}
}

 

       决策树的叶节点保存有偏移量,样本在决策树森林中通过的叶节点的偏移量的和为样本形状的偏移量。在多级森林的情况下,形状的变化是一级森林结束后,而不是每一棵决策树。

2.2.3 全局二值特征

        对于一个样本,如果经过决策树,落在决策树地一个叶节点,那么形成特征10000000 (八个叶节点,需保证每棵决策树叶节点一致),如果落在第二个叶节点那么形成特征01000000。将一级中的决策树的特征按次序组合,就形成用于回归的全局二值特征。

        在训练的过程中,我们得到N个特征Fi,组合形成F,设样本的形状点数量为68,那么对应有136个偏移量,N个Rij,形成Rj,通过解2中的方程形成136个W。假如有136棵决策数,那么Fi的维度是136x8=1088, Wi的维度是1088x1,那么W的维度是1088x136。

        从这些数据可以看出,W可以分散到各个叶节点,那么就形成每个叶节点包含136个偏移量,这样在预测的时候就不用带入2章中的方程了,直接累加即可。这就是3000fps快的原因之一。

 

     

3 效果

         测试机的配置:Intel Xeon E3-1231,测试时使用单核。

       训练相关参数:人脸窗口大小96x96,单级决策数数量544,共5级,采用特殊压缩算法模型大小3.5M

       测试性能:一张人脸的对齐平均速度为1ms。估计在作者论文上提到的机器3000fps无压力。

       测试效果见下图:

 

4 总结

      本文是基于一段时间在论文复现工作的基础上,对一些方法进行记录,目前有很多关于3000fps无法复现的传言,从目前我的结果来看,应该是没有问题的。由于对3000fps模型压缩的工作做的比较出色,我认为用在手机上并没有太大的压力。

      后来,转战深度学习,效果和速度均比3000fps要好很多,这是android app:

, 支持三张人脸追踪,log中可以查看运行速度。

      邮箱:huneng1991@163.com

      QQ: 136816548

 

参考

[1]  Face Alignment at 3000 FPS via Regressing Local Binary Features

[2] X. Cao, Y. Wei, F. Wen, and J. Sun. Face alignment by explicit shape regression. In Computer Vision and Pattern Recognition (CVPR), 2012 IEEE Conference on. IEEE,2012.

[3] http://blog.csdn.net/huneng1991/article/details/51606140

 

 

这篇关于人脸对齐 3000fps的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/255689

相关文章

golang内存对齐的项目实践

《golang内存对齐的项目实践》本文主要介绍了golang内存对齐的项目实践,内存对齐不仅有助于提高内存访问效率,还确保了与硬件接口的兼容性,是Go语言编程中不可忽视的重要优化手段,下面就来介绍一下... 目录一、结构体中的字段顺序与内存对齐二、内存对齐的原理与规则三、调整结构体字段顺序优化内存对齐四、内

自定义结构体的对齐问题

一、跨平台通用数据类型 之前的一篇博客Linux数据类型(通用移植),已经自定义尝试解决了数据通用类型问题。 这里通过源码进行分析,利用源码进行解决问题。在<stdint.h>中我们发现: typedef signed char int8_t;typedef unsigned char uint8_t;typedef short int16_t;typedef unsigned s

SylixOS ARM平台下内存对齐访问

1.内存对齐 1.1     内存对齐概要 现代计算机中内存空间都是按照byte划分的,从理论上讲对任何类型的变量的访问可以从任何地址开始,但实际情况是在访问特定变量的时候经常在特定的内存地址访问,这就需要各类型数据按照一定的规则在空间上排列,而不是顺序的一个接一个的排放,这就是对齐。 1.2     内存对齐作用和原因 各个硬件平台对存储空间的处理上有很大的不同。一些平

如何在Word中插入表格并进行高级格式化:冒号对齐、添加下划线并分栏

如何在Word中插入表格并进行高级格式化:详细教程 在Word中,表格是一个非常常用的工具,能够帮助我们更好地组织和展示信息。除此之外,本文还将深入探讨如何实现冒号对齐、添加专业的下划线以及隐藏表格线等高级技巧。通过这些技巧,能让你的文档更具美观性与专业性。 第一步:在Word页面上插入表格(大小为6行、2列) 插入表格 打开Word文档,将光标定位到想要插入表格的位置。点击菜单栏中的

[数据集][目标检测]人脸口罩佩戴目标检测数据集VOC+YOLO格式8068张3类别

数据集格式:Pascal VOC格式+YOLO格式(不包含分割路径的txt文件,仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数):8068 标注数量(xml文件个数):8068 标注数量(txt文件个数):8068 标注类别数:3 标注类别名称:["face_with_mask","face_without_mask","mask"] 每个类别

【数据应用案例】卡通人脸检测

案例来源:@将门创投 案例地址: https://mp.weixin.qq.com/s/rze_vnSRriQ5tIzMd-bDug 1. 卡通人脸检测的用处 1)搜索引擎检索 2)通过识别与语音合成帮助视障用户享受卡通作品 3)内容控制和审查的一部分 2. 数据集:IIIT-CFW卡通数据集,包含8928张带标记卡通人脸图像,

CodeWarrior编码时设置大括号{}对齐方式

在利用CodeWarrior写代码时后,每次写了if(),然后写“{}”,“{”会跟在"if()"之后,设置方式如下图:

Word封面对齐技巧

文章目录 前言一、对齐封面1. 点击视图,添加标尺2. 选中文字,右击段落3. 点击制表符,设置制表位位置4. 鼠标点击“:”后面,点击“Tab”键5. 按住“Ctrl”键,选中没对齐的文字,点击“中文板式”,调整宽度6. 最终效果 前言 本章使用的软件是WPS2019,简单介绍Word使用中封面对齐技巧,仅供参考。 一、对齐封面 1. 点击视图,添加

Python--基于OpenCV数据集的人脸定位和识别

就是调个库,没什么好说的。上代码: 事前准备: python安装两个库。 pip install opencv-pythonpip install opencv-contrib-python 到cv2文件夹下取出三个文件,复制到工作区: haarcascade_frontalcatface.xmlhaarcascade_frontalcatface_extended.xmlhaarca

理解内存对齐

序言  相信大家已经看过不少关于如何计算内存对齐的文章了,但是大家大家有思考过吗,为什么需要内存对齐?为什么要做浪费内存资源的事?直接让数据挨在一起不就行了吗?本篇文章将简单介绍为什么需要内存对齐,以及理解了之后,我们再来看内存对齐。 1. 为什么需要内存对齐  当我们在看一本英语书时,对于熟悉的单词,我们在大脑里面会迅速的反应,并将它翻译为对应的中文含义。但是,当一个单词出现如下情况: