在机器学习、图像处理中,经常要计算两个特征向量之间形状的距离,比如我用face++检测到两张人脸的特征点数据,我们要用人脸的特征点计算出这两张人脸的之间的相似度,这个时候我们就需要对这两张人脸进行对齐操作,就是AAM算法中的Procrustes Analysis对齐算法。这个是基础算法,因此在这里做一下笔记,贴一下代码,以便日后调用,因为最近搞项目,老是用到这个算法。

一、固定两点对齐


假如我要计算线段PQ变换成P'Q'的变换矩阵,那么我首先要计算计算向量PQ和向量P'Q'的变换矩阵(旋转和缩放),然后再以P点为源点,把P点平移到P'点。因此过程分成两步:

1、计算向量间的变换矩阵

<span style="font-size:18px;">//计算两个线段之间的变换矩阵,求解线段(Line2P,Line2Q)往(Line1P,Line1Q)的变换矩阵
Eigen::Matrix2d CSearchFace::Transform_Line_Segment(cv::Vec2f Line1P,cv::Vec2f Line1Q,cv::Vec2f Line2P,cv::Vec2f Line2Q)
{Eigen::Vector2d A;Eigen::Vector2d B;A(0)=Line1P[0];A(1)=Line1P[1];B(0)=Line1Q[0];B(1)=Line1Q[1];Eigen::Vector2d C;Eigen::Vector2d D;C(0)=Line2P[0];C(1)=Line2P[1];D(0)=Line2Q[0];D(1)=Line2Q[1];Eigen::Vector2d cd=D-C;Eigen::Vector2d ab=B-A;Eigen::Matrix2d cof;cof(0,0)=cd(0);cof(0,1)=cd(1);cof(1,0)=cd(1);cof(1,1)=-cd(0);Eigen::Vector2d tr=cof.inverse()*ab;cof(0,0)=tr(0);cof(0,1)=tr(1);cof(1,0)=-tr(1);cof(1,1)=tr(0);return cof;}</span>

2、平移变换。

下面以人脸特征点的对齐为例子,计算两个人脸特征点之间的相似度,因为最近做到的项目是参考文献《Data-Driven Face Cartoon Stylization》的算法,里面涉及到从脸型库里面寻找与用户输入的人脸最相似的脸型。在第4部分的第4段,Chin and mouth的算法,脸庞之间距离的计算方法是通过固定脸庞上的两个顶点,然后进行计算距离,因此我把代码贴一下:

//算法通过固定脸庞上的1、13号点,对这两个点进行变换对齐,然后计算1~13号点之间的距离总和
float CSearchFace::GetFaceDistance(vector<cv::Vec2f>face1_landmark,vector<cv::Vec2f>face2_landmark)
{float sum_dis=0;vector<cv::Vec2f>result0;//计算向量间的变换矩阵Eigen::Matrix2d tm=Transform_Line_Segment(face1_landmark[1],face1_landmark[13],face2_landmark[1],face2_landmark[13]);//平移Eigen::Vector2d Line1P(face2_landmark[1][0],face2_landmark[1][1]);Eigen::Vector2d Movv(face1_landmark[1][0],face1_landmark[1][1]);for (int i=1;i<14;i++){Eigen::Vector2d pt(face2_landmark[i][0],face2_landmark[i][1]);Eigen::Vector2d dst_point_eigen=pt-Line1P;Eigen::Vector2d src_point_eigen=tm*dst_point_eigen+Movv;//变换后的点result0.push_back(cv::Vec2f(src_point_eigen(0),src_point_eigen(1)));//最后的结果//距离计算cv::Vec2f disv=cv::Vec2f(src_point_eigen(0),src_point_eigen(1))-face1_landmark[i];sum_dis+=sqrt(disv[0]*disv[0]+disv[1]*disv[1]);}m_restul=result0;return sum_dis;}

二、相似变换对齐

《Data-Driven Face Cartoon Stylization》的算法嘴部的对齐算法与脸庞的对齐算法不一样,嘴部是通过相似变换的算法实现的。或者称之为仿射变换

python 版本:

def transformation_from_points(points1, points2):"""Return an affine transformation [s * R | T] such that:sum ||s*R*p1,i + T - p2,i||^2is minimized."""points1 = points1.astype(numpy.float64)points2 = points2.astype(numpy.float64)c1 = numpy.mean(points1, axis=0)c2 = numpy.mean(points2, axis=0)points1 -= c1points2 -= c2s1 = numpy.std(points1)s2 = numpy.std(points2)points1 /= s1points2 /= s2U, S, Vt = numpy.linalg.svd(points1.T * points2)R = (U * Vt).Treturn numpy.vstack([numpy.hstack(((s2 / s1) * R,c2.T - (s2 / s1) * R * c1.T)),numpy.matrix([0., 0., 1.])])

c++版本:

//把src往ref进行变换对齐
Eigen::Matrix<float, Eigen::Dynamic, Eigen::Dynamic> CSearchMouth::Similarity_transform_2d(vector<Vector2> src,vector<Vector2>ref, vector<Vector2>&dst)
{int count=ref.size();dst.resize(count);assert(count >= 3);Eigen::Matrix<float, Dynamic, Dynamic> A(2 * count, 4), X, B(2 * count, 1), S;for (int i = 0; i < count; i++){A(i, 0) = src[i].x;A(i, 1) = src[i].y;A(i, 2) = 1;A(i, 3) = 0;A(i + count, 0) = src[i].y;A(i + count, 1) = -src[i].x;A(i + count, 2) = 0;A(i + count, 3) = 1;B(i, 0) = ref[i].x;B(i + count, 0) = ref[i].y;}X = A.jacobiSvd(ComputeThinU | ComputeThinV).solve(B);Eigen::Matrix<float, 2, 3> M;M << X(0, 0), X(1, 0), X(2, 0), -X(1, 0), X(0, 0), X(3, 0);for (int i = 0; i < count; i++){dst[i].x = M(0, 0) * src[i].x + M(0, 1) * src[i].y + M(0, 2);dst[i].y = M(1, 0) * src[i].x + M(1, 1) * src[i].y + M(1, 2);}return M;
}

本文地址:http://blog.csdn.net/hjimce/article/details/47019223     作者:hjimce     联系qq:1393852684   更多资源请关注我的博客:http://blog.csdn.net/hjimce                原创文章,转载请保留本行信息。

基础知识(五)对齐变换相关函数相关推荐

  1. git 分支复制_Git基础知识(五)

    Git基础知识(五) 分支 都说Git的分支是它的必杀技特性,由于没有接触过太多的版本管理工具,就使用过的SVN来说,两者真的差别巨大.SVN创建一个分支,需要将内容复制一遍!这个时间真的是非常的漫长 ...

  2. JavaSE基础知识(五)--面向对象代码实现初步(实现一个简单的类类型代码)

    Java SE 是什么,包括哪些内容(五)? 本文内容参考自Java8标准 一.面向对象(代码实现): 首先,在这里我需要说明一个根本性的问题:实际上,面向对象编程包括了两部分,一个是你的编程思想,一 ...

  3. C# 基础知识 (五).变量类型和字符串处理

            这篇文章是阅读<C#入门经典(Beginning C#)>书籍里面的内容,作者Karli Watson.主要包括自己缺乏的一些C#基础知识和在线笔记使用,文章主要包括C#简 ...

  4. Java基础知识(五) 字符串与数组

    Java基础知识 字符串与数组 1. 字符串的创建与存储的机制是什么 2. "==".equals和hashCode有什么区别 3. String.StringBuffer.Str ...

  5. 一、BLDC矢量控制基础知识:Clarke变换和Park变换

    BLDC矢量控制坐标变换 本文的目的在于梳理三相电机旋转矢量以及Clarke变换和Park变换的知识并给出推导. 文章目录 BLDC矢量控制坐标变换 前言 一.从旋转矢量说起 二.Clarke变换 三 ...

  6. 卷积神经网络基础知识五(mobilenet)

    一.简单介绍 1.1 绪论 论文下载地址: MobileNets: Efficient Convolutional Neural Networks for Mobile Vision Applicat ...

  7. JavaSE基础知识(五)--面向对象思想概述

    Java SE 是什么,包括哪些内容(五)? 本文内容参考自Java8标准 一.面向对象: 1.回顾前面的博文("了解这个开头,更有利于了解对象以及面向对象的思想") 首先我们知道 ...

  8. java基础知识五、六、七、八

    第五章 在较大的数之前先增加较小数是减小误差的一种方法. 第六章 方法签名(Method Signature)指方法名称.参数类型和参数数量.java编译器根据方法签名决定使用哪个方法. 调用方法时, ...

  9. Matlab基础知识五

    第五节 1.subplot() plot() 绘制二维图像,一般默认格式为plot(x,y),也可以用带属性的格式,增加线条的属性(标记符号.线型.颜色.粗细等) subplot(m,n,1); 改变 ...

最新文章

  1. Linux下C的线程同步机制
  2. Insert SQL Query插入效率优化
  3. Taro+react开发(46)taro中环境判断
  4. 如果你还不了解GBDT,不妨看看这篇文章
  5. pacific-atlantic-water-flow(不错)
  6. 形态学上的图像顶帽运算和黑帽运算是什么?
  7. 迁入阿里云后:解决了一个IIS动态内容压缩的问题
  8. 多线程编程之优先级翻转问题
  9. “站长也疯狂,开车盛宴”——如何选择运维产品
  10. Django框架详解
  11. 清华大学范玉顺互联网与大数据_互联网+时代的互联网思维与大数据思维
  12. imx8qm HDMI-TX调试
  13. 【UML建模案例】小型网上书店系统
  14. 单片机上面的继电器工作原理及其作用
  15. 我是如何纯靠技术在大学月入上万,收获人生第一个10W
  16. oss文件服务器是什么,对象存储oss是什么
  17. 如何使用Nginx防御DDoS攻击?
  18. 安利一个在线图片转ICO格式的网站
  19. Android 仿淘宝属性标签页
  20. Tensorflow 的NCE-Loss的实现和word2vec

热门文章

  1. java shiro登录实例_使用Shiro实现登录成功后跳转到之前的页面
  2. mysql安装(glibc版本安装5.7.22)
  3. c语言皮尔森系数程序,按条件选入观测;皮尔森相关系数
  4. 计算机硬件外围设备介绍,天津2012年自考“计算机外围设备使用与维护”课程考试大纲...
  5. 我们大家都知道mysql_10个mysql中select语句的简单用法
  6. Modbus​协议​深入​讲解_NI
  7. python学习之模块--模块(五)
  8. Java集合——概述
  9. android webview js交互 第一节 (java和js交互)
  10. POJ-1904-King's Quest(强连通图)