本文中,我们通过Procrustes analysis来处理特征点,Procrustes analysis算法可以参考:http://en.wikipedia.org/wiki/Procrustes_analysis

      在数学上,Procruster analysis就是寻找一个标准形状,然后把所有其它特征点数据都和标准形状对齐,对齐的时候采用最小平方距离,用迭代的方法不断逼近。下面通过代码来了解如何实现Procrustes analysis。

//Procrustes分析的基本思想是最小化所有形状到平均形状的距离和。
Mat shape_model::procrustes(const Mat &X,
    const int itol,  //最大迭代次数
    const float ftol //精度

     )
    {

X矩阵就是多副样本图像76个特征点组成的矩阵,共152行,列数为图像的个数,每列表示一个样本图像特征点的x,y坐标。
    int N = X.cols,n = X.rows/2;

    //所有的形状向量(特征)对齐到原点,即每个向量的分量减去其平均值,每列是一个形状向量。
    Mat P = X.clone();
    for(int i = 0; i < N; i++)
        {
        Mat p = P.col(i); //第i个列向量
        float mx = 0,my = 0;
        for(int j = 0; j < n; j++) //x,y分别计算得到平均值。
            {
            mx += p.fl(2*j);
            my += p.fl(2*j+1);
            }
        mx /= n; my /= n;

        for(int j = 0; j < n; j++)
            {
            p.fl(2*j) -= mx;
            p.fl(2*j+1) -= my;
            }
        }

//优化缩放和旋转
    Mat C_old;
    for(int iter = 0; iter < itol; iter++)
        {  

      注意下边的一行代码,会把每个图像对齐到原点后的特征点x,y分别加起来,求平均值,得到一个152*1的矩阵,然后对该矩阵进行归一化处理,归一化后的形状称作标准形状或者权威形状。
        Mat C = P*Mat::ones(N,1,CV_32F)/N;  //计算形状变换后的平均值
        normalize(C,C); //canonical shape 标准形状(对x-进行标准化处理)
        if(iter > 0) //当两个标准形状或者标准形状的误差小于某一值,这里是ftol则,停止迭代。如果达到最大迭代次数,也退出迭代。
            {

norm函数默认是矩阵各元素平方和的根范式
            if(norm(C,C_old) < ftol)
                break;
            }
        C_old = C.clone(); //记下当前的矩阵,和下一次进行比较
        for(int i = 0; i < N; i++)
            {

              Mat R = this->rot_scale_align(P.col(i),C); //求两个形状之间的误差满足最小二乘时的旋转矩阵。即相当于两个形状"最靠近"时,需要的旋转的仿射矩阵

rot_scale_align函数求每副图像的特征点向量和平均向量满足最小二乘法时候的旋转矩阵。即求得a,b值组成的旋转缩放矩阵(注意:这儿表示旋转和缩放矩阵的组合,便于线性表示)。

        rot_scale_align函数的代码如下,原理如下面的两个图,即当前特征向量中的每个特征点经过旋转缩放变化的值和标准形状(权威形状)对应的特征点值差的平方和最小,结果得到一个2*2的旋转缩放矩阵。

Mat    shape_model::rot_scale_align(const Mat &src,    const Mat &dst)
{
//construct linear system
int n = src.rows/2;
float a=0,b=0,d=0;
for(int i = 0; i < n; i++)
{
d += src.fl(2*i) * src.fl(2*i ) + src.fl(2*i+1) * src.fl(2*i+1); //x*x+y*y
a += src.fl(2*i) * dst.fl(2*i ) + src.fl(2*i+1) * dst.fl(2*i+1);
b += src.fl(2*i) * dst.fl(2*i+1) - src.fl(2*i+1) * dst.fl(2*i );
}
a /= d;
b /= d;
//solved linear system
return (Mat_<float>(2,2) << a,-b,b,a);
}

            for(int j = 0; j < n; j++)

                {

//应用相似变换,对形状中的每一个点,应用仿射矩阵。  变化后,该特征点向量会靠近平均特征向量。之后经过反复迭代,直到平均向量和上次比较变化很小或达到最大迭代次数,退出迭代。

                float x = P.fl(2*j,i),y = P.fl(2*j+1,i);

                P.fl(2*j  ,i) = R.fl(0,0)*x + R.fl(0,1)*y;

                P.fl(2*j+1,i) = R.fl(1,0)*x + R.fl(1,1)*y;

                }

            }

        }

    return P;

    }

人脸识别中的Procruster analysis应用的更多相关文章

  1. 机器学习:PCA(人脸识别中的应用——特征脸)

    一.思维理解 X:原始数据集: Wk:原始数据集 X 的前 K 个主成分: Xk:n 维的原始数据降维到 k 维后的数据集: 将原始数据集降维,就是将数据集中的每一个样本降维:X(i) . WkT = ...

  2. (转载)人脸识别中Softmax-based Loss的演化史

    人脸识别中Softmax-based Loss的演化史  旷视科技 近期,人脸识别研究领域的主要进展之一集中在了 Softmax Loss 的改进之上:在本文中,旷视研究院(上海)(MEGVII Re ...

  3. 深度挖坑:从数据角度看人脸识别中Feature Normalization,Weight Normalization以及Triplet的作用

    深度挖坑:从数据角度看人脸识别中Feature Normalization,Weight Normalization以及Triplet的作用 周翼南 北京大学 工学硕士 373 人赞同了该文章 基于深 ...

  4. 浅谈人脸识别中的loss 损失函数

    浅谈人脸识别中的loss 损失函数 2019-04-17 17:57:33 liguiyuan112 阅读数 641更多 分类专栏: AI 人脸识别   版权声明:本文为博主原创文章,遵循CC 4.0 ...

  5. 人脸识别中的重要环节-对齐之3D变换-Java版(文末附开源地址)

    一.人脸对齐基本概念 人脸对齐通过人脸关键点检测得到人脸的关键点坐标,然后根据人脸的关键点坐标调整人脸的角度,使人脸对齐,由于输入图像的尺寸是大小不一的,人脸区域大小也不相同,角度不一样,所以要通过坐 ...

  6. 知物由学 | 基于DNN的人脸识别中的反欺骗机制

    "知物由学"是网易云易盾打造的一个品牌栏目,词语出自汉·王充<论衡·实知>.人,能力有高下之分,学习才知道事物的道理,而后才有智慧,不去求问就不会知道."知物 ...

  7. 人脸识别中的检测(在Opencv中加入了QT)

    #include <opencv2/highgui/highgui.hpp> #include <opencv2/imgproc/imgproc.hpp> #include & ...

  8. 人脸识别中的harr特征提取(转)

    影响AdaBoost人脸检测训练算法速度很重要的两方面是特征选取和特征计算.选取的特征为矩特征为Haar特征,计算的方法为积分图. (1)Haar特征:     Haar特征分为三类:边缘特征.线性特 ...

  9. 人脸识别必读的N篇文章

    一,人脸检测/跟踪 人脸检测/跟踪的目的是在图像/视频中找到各个人脸所在的位置和大小:对于跟踪而言,还需要确定帧间不同人脸间的对应关系. 1, Robust Real-time Object Dete ...

随机推荐

  1. [BZOJ4129]Haruna’s Breakfast(树上带修改莫队)

    BZOJ3585,BZOJ2120,BZOJ3757三合一. 对于树上路径问题,树链剖分难以处理的时候,就用树上带修改莫队. 这里的MEX问题,使用BZOJ3585的分块方法,平衡了时间复杂度. 剩下 ...

  2. Codeforces.810D.Glad to see you!(交互 二分)

    题目链接 \(Description\) 有一个大小为\(k\)的集合\(S\),元素两两不同且在\([1,n]\)内.你可以询问不超过\(60\)次,每次询问你给出\(x,y\),交互库会返回\(\ ...

  3. BZOJ.2462.[BeiJing2011]矩阵模板(二维Hash)

    题目链接 序列上的Hash和前缀和差不多,二维Hash也和二维前缀和差不多了. 预处理大矩阵所有r*c的小矩阵hash值,再对询问的矩阵Hash. 类比于序列上\(s[r]-s[l-1]*pow[r- ...

  4. BZOJ.4516.[SDOI2016]生成魔咒(后缀自动机 map)

    题目链接 后缀数组做法见这. 直接SAM+map.对于每个节点其产生的不同子串数为len[i]-len[fa[i]]. //15932kb 676ms #include <map> #in ...

  5. springmvc学习总结(一) -- 从零搭建,基础入门

    1.新建maven项目 参考mybatis学习笔记(五) -- maven+spring+mybatis从零开始搭建整合详细过程(上)第一部分,修改配置 2.修改pom.xml 文件 <proj ...

  6. Codeforces Round #373 (Div. 2) B. Anatoly and Cockroaches 水题

    B. Anatoly and Cockroaches 题目连接: http://codeforces.com/contest/719/problem/B Description Anatoly liv ...

  7. UVALive 6889 City Park 并查集

    City Park 题目连接: http://acm.hust.edu.cn/vjudge/contest/view.action?cid=122283#problem/F Description P ...

  8. mySql---数据库索引原理及优化

    一.写在前面 本文以MySQL数据库为研究对象,讨论与数据库索引相关的一些话题.特别需要说明的是,MySQL支持诸多存储引擎,而各种存储引擎对索引的支持也各不相同,因此MySQL数据库支持多种索引类型 ...

  9. MikroTik RouterOS网址资源收集

    routeros|mikrotik|ros|软路由论坛|中国路由网|软件路由|软件路由器|routeros技术论坛|路由论坛 - Powered by Discuz!   Mikrotik RB450 ...

  10. 使用filezilla server搭建FTP服务器

    参考文献 http://www.pc6.com/infoview/Article_51961_all.html 背景 需要在内网环境下搭建一个FTP服务器,查阅相关资料发现使用filezilla se ...