训练好caffemodel后,提取人脸图片的特征向量
这篇博客主要介绍下用C++代码,提取出一张人脸图片的特征向量,这里的网络,是上文中用到了center loss的网络,根据论文里介绍的,我们提取出人脸图片以及该图片的上下翻转图各自经过网络在fc5层输出的特征向量,然后将两者拼起来,形成一个2倍维数的特征向量,该特征向量表征了这个人脸。这样子,我们计算出一对待验证的人脸图片各自的特征向量后,就可以计算相似度了,这里用余弦相似度。
同样的,作为C++爱好者,我还是将代码组织成一个人脸识别类 class FaceRecognition ,该类只有一个共有的接口
float getSimilarity(const Mat& lhs,const Mat& rhs,bool useFlipImg=true); //比较两个图像的余弦相似度
输入两张待识别的人脸图片(注意,这个函数不会对人脸图片进行对齐操作),计算出其余弦相似度并返回。
#include <caffe/caffe.hpp>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <algorithm>
#include <iosfwd>
#include <memory>
#include <string>
#include <utility>
#include <vector>
#include <cmath>
using namespace caffe; // NOLINT(build/namespaces)
using namespace cv;
using namespace std;//人脸验证类
class FaceRecognition{ //提取网络最后一层特征
public://构造函数,需要一个deploy.prototxt文件和一个caffemodelFaceRecognition(const string& model_file,const string& trained_file ){_net.reset(new Net<float>(model_file,TEST)); //定义一个网络_net->CopyTrainedLayersFrom(trained_file); //加载权重}float getSimilarity(const Mat& lhs,const Mat& rhs,bool useFlipImg=true){ //比较两个图像的余弦相似度//计算余弦相似度vector<float> feat1,feat2;if(useFlipImg){feat1=getLastLayerFeaturesFlip(lhs);feat2=getLastLayerFeaturesFlip(rhs);}else{feat1=getLastLayerFeatures(lhs);feat2=getLastLayerFeatures(rhs);}return std::max<float>(0,getSimilarity(feat1,feat2));}private:shared_ptr<Net<float> > _net; //CNN网络float getMold(const vector<float>& vec){ //求向量的模长int n = vec.size();float sum = 0.0;for (int i = 0; i<n; ++i)sum += vec[i] * vec[i];return sqrt(sum);}//求两个向量的余弦相似度float getSimilarity(const vector<float>& lhs, const vector<float>& rhs){int n = lhs.size();assert(n == rhs.size());float tmp = 0.0; //内积for (int i = 0; i<n; ++i)tmp += lhs[i] * rhs[i];return tmp / (getMold(lhs)*getMold(rhs));}//center loss中,是将原图的特征向量和上下翻转图的特征向量拼接起来,返回最终的特征向量vector<float> getLastLayerFeaturesFlip(const Mat& _img){vector<float> result1 = getLastLayerFeatures(_img); //原图的特征向量,需要再计算翻转图的特征向量Mat flipImg;flip(_img, flipImg, 0); //上下翻转vector<float> result2 = getLastLayerFeatures(flipImg);for (int i = 0; i<result2.size(); ++i)result1.push_back(result2[i]);return result1;}vector<float> getLastLayerFeatures(const Mat& _img){ //求一张图片经过最后一层(fc5)的特征向量Mat img = _img.clone();img.convertTo(img, CV_32FC3); //转为浮点图Blob<float>* inputBlob = _net->input_blobs()[0];int width = inputBlob->width(); //网络规定的输入图片的宽度和高度int height = inputBlob->height();resize(img, img, Size(width, height)); //将测试图片进行调整大小img = (img - 127.5)*0.0078125; //减均值,再缩放到-1 到 1float* data = inputBlob->mutable_cpu_data(); //将图片的像素值,复制进网络的输入Blobfor (int k = 0; k<3; ++k){for (int i = 0; i<height; ++i){for (int j = 0; j<width; ++j){int index = (k*height + i)*width + j; //获取偏移量data[index] = img.at<Vec3f>(i, j)[k];}}}vector<Blob<float>* > inputs(1, inputBlob);const vector<Blob<float>* >& outputBlobs = _net->Forward(inputs); //进行前向传播,并返回最后一层的blobBlob<float>* outputBlob = outputBlobs[0]; //输出blobconst float* value = outputBlob->cpu_data();vector<float> result;for (int i = 0; i<outputBlob->count(); ++i) //将输出blob里的特征数值,拷贝到vector里并返回result.push_back(value[i]);return result;}
};
代码进行了大量的注释,且大量中间过程,都在私有函数里,最终直接调用getSimilarity函数就能得到两张图片的相似度。
还有一点需要注意的是,因为代码中,强调的是输出最后一层的输出值,所以我们的deploy.prototxt文件,要把softmax层以及accuracy层什么的都注释掉,直到最后一个我们想输出的层,比如我们这里是要得到fc5的输出值,则要把fc5层的后面的都注释掉。具体文件可以参看作者的GitHub。
https://github.com/ydwen/caffe-face
部分效果如下
我们这里使用的人脸检测以及人脸对齐的方法是上上篇博客中的方法,MTCNN,论文是
Joint Face Detection and Alignment using Multi-task Cascaded Convolutional Networks
然后,训练人脸图片用到神经网络以及方法(center loss)以及GitHub分别是
ECCV16 《A Discriminative Feature Learning Approach for Deep Face Recognition》
https://github.com/ydwen/caffe-face
训练好caffemodel后,提取人脸图片的特征向量相关推荐
- DeepFaceLab小白入门(4):提取人脸图片!
通过上面级片文章,你应该基本知道了换脸的流出,也能换出一个视频来.此时,你可能会产生好多疑问,比如每个环节点点到底是什么意思,那些黑漆漆屏幕输出的又是什么内容,我换脸效果这么差,该如何提升?等等,好奇 ...
- CV之FR:基于DIY人脸图像数据集(每人仅需几张人脸图片训练)利用Hog方法提取特征和改进的kNN算法实现人脸识别并标注姓名(标注文本标签)—(准确度高达100%)
CV之FR:基于DIY人脸图像数据集(每人仅需几张人脸图片训练)利用Hog方法提取特征和改进的kNN算法实现人脸识别并标注姓名(标注文本标签)-(准确度高达100%) 目录 基于DIY人脸图像数据集( ...
- 利用人脸微笑数据集训练识别模型,完成对人脸图片微笑识别
目录 一.数据集下载 二.提取人脸并判别是否为笑脸 (一)数据处理 (二)测试 三.视频识别并保存图片 四.总结 五.参考链接 一.数据集下载 1.链接:https://pan.baidu.com/s ...
- ML之SVM:调用(sklearn的lfw_people函数在线下载55个外国人图片文件夹数据集)来精确实现人脸识别并提取人脸特征向量
ML之SVM:调用(sklearn的lfw_people函数在线下载55个外国人图片文件夹数据集)来精确实现人脸识别并提取人脸特征向量 目录 输出结果 代码设计 输出结果 代码设计 from __fu ...
- 训练O_net网络,并测试图片
训练O_net网络,并测试图片 上一篇,我们已经知道如何生成O_net训练集,这次我们开始训练Onet网络. 训练完成后,保存权重,我们随机抽取一张照片,测试一下效果. 代码: train_Onet. ...
- 超分辨率:将背景和人脸分离 ,人脸、背景分别做增分后将人脸贴回背景图
景(自然景物超分辨率)和人脸超分辨率相结合,可以实现更高的超分效果,提升结果的观感. # 问题描述与原因分析: 对一张有人脸的图片做超分时候,如果单纯是使用一个自然场景的超分辨率网络,背景部分应该可以 ...
- 使用SAP Leonardo上的机器学习服务提取图片的特征向量
要想提取图片的特征向量,首先得知道特征向量是什么. 我们假设这样一个服务场景,技师上门维修某设备,发现上面某零件损坏了,假设这位技师由于种种原因,没能根据自己的经验识别出这个零件的型号.此时技师掏出自 ...
- C#人脸识别入门篇--提取人脸特征值及人脸识别
转自:http://blog.csdn.net/feishixin/article/details/77397027 如何识别多个人脸 在开始之前,先解决一个疑问,这个SDK可以识别多个人脸吗.答案当 ...
- 从.caffemodel/.caffemodel.h5提取Caffe模型的参数
系列博客目录:Caffe转Pytorch模型系列教程 概述 目录 一.通用的提取参数方法 1.编译Caffe 2.打印.caffemodel的网络参数 3.保存.caffemodel的网络参数 二.提 ...
- php识别人脸并提取特征值,C#人脸识别入门篇--提取人脸特征值及人脸识别
如何识别多个人脸 在开始之前,先解决一个疑问,这个SDK可以识别多个人脸吗.答案当然是可以的.在上一章节中我们实现了识别单个人脸的功能. 如果要识别多个人脸,需要进行下面的设置. 定义人脸的识别数目范 ...
最新文章
- mysql外键约束视频教学_外键约束案例_MySQL数据库 快速入门 基础+实战 视频教程_MySQL视频-51CTO学院...
- 后台开发经典书籍--unix网络编程
- 在windows上Matlab 编译MatConvNet
- android 8.0 调系统拍照_Android通知栏微技巧,8.0系统中通知栏的适配
- otis电梯服务器tt使用说明_南充私人电梯
- canvas笔记-在canvas中使用其他HTML元素
- java输入年月输出日历_java输入年份打印该年份的年历
- Linux下文件系统目录结构
- DB层面上的设计 分库分表 读写分离 集群化 负载均衡
- System x Windows Server驱动下载
- U盘量产大致研究思路
- 2D基本知识入门学习
- 三国志战略版新赛季:先锋斥候北定中原
- 头歌 Linux 远程联机服务(二)- Rsh服务器
- ‘C:\Users\Administrator\Desktop\gitSpace\dj-2\dj\vue-manager-dj\node_modules\node-sass\vendor‘
- IPA转APP的方法和APP转IPA的方法
- 二建《机电》案例 100 问
- 【3C认证】儿童安全座椅3C认证本年9月1日起实施
- ArduinoMega2560 引脚表
- Python爬虫-BeautifulSoup
热门文章
- [渝粤教育] 西安交通大学 土力学 参考 资料
- Android蓝牙完全学习手册
- 偏见:人工智能辅助决策的隐患
- 知识总结2:Django常见面试题总结(持续更新)
- webstorm 下载并设置jade、less
- verilog语法基础
- Android性能优化之利用LeakCanary检测内存泄漏及解决办法
- Matlab吴恩达机器学习编程练习ex5:正则化线性回归和偏差v.s. 方差Regularized Linear Regression and Bias v.s. Variance
- quartus之BSF自底向上
- DEDECMS5.7自动采集更新伪原创插件高级版GBK