用上次提供的手工标定的脚本,我们已经得到了一些训练样本,接下来就该进行训练了。
AAM和ASM的形状和纹理(ASM用的是形状landmark点附近的局部纹理,AAM用的是base shape mesh内部的全部像素)训练都是独立进行的,训练的方法都是主成分分析(PCA),把形状或纹理投到训练样本撑起的子空间(subspace)中去,把人脸形状或纹理利用子空间中相对较少的维数来表达。样本在子空间中得到的坐标值,又可以称为模型参数。也就是说任何一个样本都能表达成用一组正交向量基的加权和的形式,这些向量基表示高维空间中的坐标轴,这些权重系数(模型参数)表示样本在坐标轴上投影得到的坐标值。PCA使用的KL变换,是一种线性变换,它把样本集合所在的高维空间坐标轴进行了平移和旋转变换,变换后,坐标原点变到样本聚类中心(这就需要样本在空间中是聚类的,比如都是正脸的形状或纹理),坐标轴的方向旋转到与聚类集合的主轴方向平行(假设样本聚类成一个高维椭球),序号在前的坐标轴的集中的能量较多,排在后面的只能表达一些噪声,通过忽略后面的表达能力较弱的坐标轴,达到降维的目的。比如68×2=136维的形状矢量,可以用较少的几十个参数来表达。PCA计算可以非常容易地用matlab的svd函数(或svds)实现,比如这样
[U,S] = svds(x,s);%x是样本集合,每个样本对应一列,均值为0,s表示最大能量的s个eigenvalue
Evalues=diag(S).^2;%eigenvalue,S是singular value矢量
Evectors=U; %本征矢量eigenvectors
在开始做PCA之前,来至不同图像的形状样本,都要经过一个4个参数(表示位移,平面内旋转和变比)的相似变换,变换到和它们的平均形状对齐。而这个平均形状是在变换后的样本上得到的,这是个先有鸡还是先有蛋的问题。具体做法用到迭代步骤:先给定一个平均形状的初始值,大家都向它对齐,然后计算均值,这个均值每次都要经过规范化,比如让重心为0,方差为一个固定数100,具体如下:
%% aligne all shapes 形状都表达成(x1,x2,...y1,y2...)的136维的矢量
alishapes = shapeall;
meanshape = alishapes(:,1);
for round=1:50 %循环次数50
meanshape = norm_meanshape(meanshape);
for i=1:ls %所有样本,pntnum=68
[shape_new, M] = align2shape( [alishapes(1:pntnum,i),alishapes(1+pntnum:end,i) ],...
[meanshape(1:pntnum),meanshape(1+pntnum:end)], ones(pntnum,1) );
alishapes(:,i) = [shape_new(:,1);shape_new(:,2)];
end
meanshape = mean(alishapes,2);
end
我手里有80个训练样本,最后的对齐的样本如下,红点是meanshape:
PCA得到的头两个坐标轴(本征矢量)对应的本征值在方差(sqrt(engenvalue))正负3之间变化,中间那个是meanshape,也可以称为base mesh:
下面是把平均形状画在一个宽高分别为133和153像素图像上的情形,形状重心对应图像的中心点:
这个图像是AAM用来训练纹理用的,作为一个摆放不同大小的人脸样本图像的标准尺度,所有图像样本都要warp到这个平均形状内部上(上篇博客文章最后那个图),它内部对应的像素个数决定了warp和纹理子空间的计算量。 如果使用多分辨率AAM,则可以以它为基础构造图像金字塔。
https://blog.sciencenet.cn/blog-465130-454882.html
上一篇:
ASM/AAM手工标定的Matlab脚本下一篇:
实验:OpenGL的增强现实