非刚性人脸跟踪(2)

2019-09-01 18:37

ft_data类实现了很多便利的方法用来访问数据。为了在数据集中访问每一个图像,get_image函数通过指定的索引idx导入图像,并且可选择地围绕y轴进行镜像图像。如下: Mat ft_data::get_image(const int idx,const int flag) {

//const int idx;//图像的索引用来从文件导入

//const int flag;//0=gray,1=gray+flip,2=rgb,3=rgb+flip;//flip镜像翻转 Mat img,im;

if(flag<2) img=imread(imnames[idx],0); esle img=imread(imnames[idx],1);

if(flag%2!=0) flip(img,im,1);else im=img; return im; }

将(0,1)标志传递给OpenCV的imread函数用来指按3通道彩色图像的形式的导入还是按单通道灰色图像导入。标志位传递给OpenCV的flip函数用来指定绕在y轴进行镜像。

为了用特殊的索引访问对应与图像的点集,get_points函数一个存储浮点型坐标的容器,带有可选的镜像索引,如下:

ft_data::get_points(cosnt int idx,const bool flipped) {

//const int idx相应点的图像索引

//const bool flipped;是否将图像绕在Y轴进行旋转 if((idx<0)||idx>=(int)imnames.size())))

return vector();//如果访问的图像不存在,返回空的容器 vector p=ponts[idx]; if(flipped) {

Mat im=this->get_image(idx,0);int n=p.size(); vector q(n);//初始化N个空的对象 for(int i=0;i

q[i].x=im.cols-1-p[symmerty[i]].x;//n为点的个数。 q[i].y=p[symmetry[i]].y; }return q; return p; } } }

注意当指定了镜像标记时,这个函数调用get_image函数。这需要判断图像的宽度,以用来纠正镜像人脸特征坐标。一个更有效的设计是传递图像的宽度作为一般变量。最后,在这个函数中symmerty成员变量的用法被阐述。一个特殊索引的镜像特征位置仅仅是symmetry变量的索引指定的位置和它的x坐标的翻转和偏移。

如果指定的索引在数据集中不存在,get_image和get_points函数均返回空的结构体。同样

可能的是,并不是集合中的所有图像都被注释。人脸跟踪算法可以设计来处理缺失的数据,然而,这些实现通常相当的复杂并且超出了本章的范围。ft_data函数实现了从集合中移除哪些没有相应注释的样本的功能,如下:

void ft_data::rm_incomplete_samples()//rm =rremove {

int n=ponts[0].size(),N=ponts.size();

for(int i=0;i

if(int(points[i].size())!=n) {

points.erase(points.begin()+i);

imnames.erase(imnames.begin()+i);i--; }else {

int j=0; for(;j

if((points[i][j].x<=0||(points[i][j].y<=0)) break; }

if(j

points.erase(points.begin()+i);

imnames.erase(imnames.begin()+i);i--; } } } }

简单的例子是,大多数量的注释被假定为是权威的样本。拥有点集少于许多数量的点的数据实例将采用容器的erase函数将其从集合中移除。同时也注意到带有(x,y)坐标小于0的点被认为在其相应的图像上缺失(可能是由于遮挡,差的可见度,或者模糊性)。

ft_data类实现序列化函数read和write,并且因此可以简单地存储和导入。例如,保存一个数据集的简单做法如下:

ft_data D;//示例数据结构 ..//填充数据

save_ft(“mydata.xml”,D);//保存数据

为了可视化数据集,ft_data函数实现了一些画图功能。他们的用法在visualize_annotations.cpp文件中阐述。这个程序导入用命令行指定的文件中的注释数据,移除不完全的样本,并且显

示带有相应注释的、对称,连接叠加的训练图像。OpenCv的highgui模块的一些显著的特征在这里示范。尽管相当基本并且不适合复杂用户接口。OpenCV的highgui模块的功能在计算机视觉应用中对于导入和可视化数据和算法输出非常有用。与其他的计算机视觉库相比,这可能是Opencv的品质。

注释工具:

为了用本章的代码产生注释,一个基本的注释工具可以在annotate.cpp文件中找到。这工具用视频流或者文件或者相机作为输入。使用这个工具的程序的四个步骤如下列出:

1、捕捉图像:在这第一步中,图像流显示在屏幕上,用户通过按S键选择图像用来注释。用来注释的最好的特征集是哪些最大的跨度面部行为的范围,这些面部行为是人脸跟踪系统需要跟踪的。

2、注释第一个图像:在第二步中,将第一阶段捕获,选择的图像提供给用户。然后用户接着点击图像上需要跟踪的附属于面部特征的位置。

3、注释连通性:在第三步,为了更好的可视化一个模型,需要定义点的连通性结构。这里,提供给用户先前阶段同样的图像,现在的任务是点击一些点对集,一个接一个的,用来为人脸模型建立连通结构。

4、注释对称性:在这一步,任然使用同样的图像,用户选择展现双边对称性的点对。 5、注释剩下的图像:在最后一步,这里的过程类似与步骤2,除此之外用户可以浏览图像集和异步地注释他们。

有兴趣的读者可能想通过改善他们的有用性来改善这些工具,或者甚至整合一个增加的学习过程,凭借一个跟踪模型的更新,该更新通过每个增加的注释的图像和随后的用来初始化的这些点来减少注释的负担。

尽管一些公开地可以利用的数据集可以为本章开发的代码利用。(例如接下来的描述)。注释工具可以被用来建立指定人脸跟踪模型,通常该模型比一般的,单独的人,相对应的人执行更好的结果。

预注释数据(MUCT数据集)

开发人脸跟踪系统的一个障碍因素是乏味的和易于出错的手动地注释大量图片集的过程,这些图像带有大量的点。为了为本章接下来的工作的目的减轻这个过程,公开地可以利用的MUCT数据集可以通过下面的连接下载: http://www/milbo.org/muct.

数据集由3755个注有67个特征点人脸图像组成。数据集的主题在年龄和种族,和许多不同光照环境和头的姿势情况下捕捉中变化。。

为了用本章的代码使用MUCT数据集,执行下面的步骤:

1、下载数据集。在这一步,数据集中所用的图像可以通过下载文件muct-a-jpg-v1.tar.gz到muct-e-jpg-v1.tar.ga,并且解压他们来获得。这将产生包含所有图像的新的文件夹。

2、下载注释:在这一步,下载文件包含注释muct-landmarks-v1.tar.gz保存。解压到和先图片的同样的文件夹呀。

3、利用注释工具定义连接和对称:在这一步,来至命令行,发布命令 ./annotate -m $mdir -d $odir,这里$mdir指示MUCT数据集保存的路径文件夹,$ofir指示annotaion.yaml文件夹,包含数据以ft_data对象的形式被写入存储。

注释:MUCT数据的使用促进在本章对人脸跟踪代码功能描述有一个快速的入门。 几何约束 在人脸跟踪,几何引用了预定义点集的空间配置,这些点集对应于人脸上物理连续位置。(例如眼角,鼻尖和眼毛边缘)。这些点的特殊选择是应用依赖的,一些应用需要超过100个点的稠密集,并且其他仅需要一个稀疏选择。然而人脸跟踪算法的的鲁棒性通常伴随着点数目的更加而改善,因为他们分开的测量值可以通过他们相关空间依赖性来增强彼此。例如,知道一个眼角的位置是对于期待鼻子在哪里定位是一个好的指示。然而通过增加点的数目来获得鲁棒性的改善是有限制的,典型地100个点之后性能停滞。而且,增加用来描述人脸的点集带有计算复杂度的线性增加。因此,带有计算负载严格限制的应用可能带有更少的点集进展的更好。

同样也有这样的情况,在在线环境下更快的跟踪经常导致更精确的跟踪。这是因为,当帧被抛弃时,两帧之间的增加察觉到的运动,以及用来在每一帧图像上寻找人脸配置的最优算法必须搜索可能的特征点配置的更大的空间。当两个帧之间的位移变大时,这个过程经常失败。 总的来说,尽管怎样最好的设计面部特征带你的选择有一个一般的指导方针,为了得到最优的性能,这一章应当专业到应用领域。

面部几何通常参数化为两个元素的组成:一个全局(刚性)转换和一般局部(非刚性)变形。全局转换解释为图像中人脸的整体布局,通常允许没有约束的改变(即,人脸可以在图像上的任何地方显示)。这包括每张图像人脸的x,y坐标,面内头部旋转,和图像中人脸的大小。另一方面,局部变形解释为面部形状交叉身份之间的不同和表情之间的不同。与全局转换相对照,这些局部变形通常有更多的限制,约束,主要是由于人脸特征的更高地结构化参数。 全局转换是2D坐标 的一般功能,适用于任何类型的对象,然而局部变形是特定对象并且必须从训练集中学习。

在这一部分,我们描述面部结构几何模型的构造,因此成为形状模型。取决于应用,它可以捕捉单个个体的表情变化,和交叉不同的人脸形状或者两者的混合。这个模型用shape_model类实现,可以在shape_model.hpp和shape_mode.cpp文件中找到。下面的代码片段是shape_model类的头的一部分,用来说明它的基本的功能。

class shape_model{//2d线性模型 public:

Mat p;//参数矢量k*1 CV_32F

Mat V;//线性子空间(2n*k) CV_32F Mat e;//参数变化(k*1) CV_32F Mat C;//连通性(c*2) CV_32S ...

void calc_params(

const vector&pts;//用来计算参数的点

const Mat &weight=Mat() //weight/point N*1 CV_32F const float c_factor=3.0)//clamping factor夹因素 .....

vector //用参数描述的形状

calc_shape(); ....

void train(

const vector >&p,//N个样本形状 const vector &con=vector()//连通性 const float frac=0.95;//用来保留的变化的分数 const int kmax=10)//用来保留的模型的最大数量 .. }

用人脸的形状代表变化的模型用子空间矩阵V和方差e进行编码。参数矢量P存储表示模型的形状的编码。连通性矩阵C同时也存储在这个类,因为它仅术语人脸形状的可视化示例。在这个类中基础兴趣的三个函数是calc_params,calc_shape,和train。calc_params函数投影一个点集到似乎可信的人脸形状的空间。calc_shape函数通过使用人脸模型(用v和e编码)解码参数矢量p来产生一个点集。train函数用人脸形状数据集学习编码模型,每一个模型由同样数量的点组成。参数frac和kmax是训练过程的参数,可以为眼前的数据特化该参数。

这个类的功能将在接下来的部分进行详细的描述,那里我们通过Procrustes分析开始,它是用来严格地登记一个点集的方法。接下来通过用通常代表局部变形的线性模型。train_shape_model.cpp和visulize_shape_model.cpp文件中的程序分别的训练和可视化模型。他们的使用将在本部分的结束进行概括。

Procrustes分析

为了建立人脸形状的一个变化模型,我们首先必须处理为加工注释的数据来移除附属于全局刚性的运动的成分。当我们用2D模型化几何时,一个刚性的运动通常代表为一个类似的转换。这包括尺度,面内旋转和平移。下面的图像阐述了在一个类似的转换下的一套允许的动作类型。从一个点集中移除全局刚性运动的过程被成为Procrustes分析.

数学上地,Procrusters分析的目的是同时找到一个权威的形状并且类似转换每一个数据实例,用这个权威的形状将他们对齐。这里,对齐的测量是用采用了权威形状的两个转换形状的最小二乘距离。为了完成这个目标,一个重复的过程在shape_model类中实现,如下: #define fl at


非刚性人脸跟踪(2).doc 将本文的Word文档下载到电脑 下载失败或者文档不完整,请联系客服人员解决!

下一篇:东北师范大学《算法分析与设计》18秋在线作业1

相关阅读
本类排行
× 注册会员免费下载(下载后可以自由复制和排版)

马上注册会员

注:下载文档有可能“只有目录或者内容不全”等情况,请下载之前注意辨别,如果您已付费且无法下载或内容有问题,请联系我们协助你处理。
微信: QQ: