1、人脸识别系统

参考网站:https://zhuanlan.zhihu.com/p/36416906

  • 人脸检测:检测出人脸在图像中的大小和位置,libfacedetection(ShiqiYu),seetaface(ShiguangShan),深度学习
  • 人脸对齐:将人脸变换到统一的角度和姿态,对人脸关键点进行相似变换(旋转,缩放,平移),尽可能转换到标准人脸
  • 人脸特征表示:向量化人脸特征,分类器判别人脸识别结果。

论文地址:https://arxiv.org/pdf/1612.02295.pdf

①人工特征论文:Blessing of Dimisionality: High Dimensional Feature and Its Efficient Compression for Face Verification(LFW数据集精度95.17%)

②深度学习人脸识别:Large-margin softmax loss for convolutional neural networks(特征与分类器间余弦角度)

论文理解:

对于一个二分类问题,softmax强制要求(即将某个样本x归为第一类,计算公式可以表述为)。如果我们将变成(m是正整数)来考虑,则当时,以下不等式自然成立:

因此,只需要保证成立,不等式自然会成立

几何解释(这里需要说明一下,论文中没有从数学公式上体现出Boundary,只是这样做了之后,效果的确提升了):

特征体现:

L1距离与cos距离

参考网站:https://zhuanlan.zhihu.com/p/34404607

突然觉得这个理论不成立呀,因为实际上样本分布是不变的,改变的是分类超平面,准备继续看一遍原文!!!

2、带遮挡的人脸识别

参考论文:http://www2.ece.ohio-state.edu/~aleix/FG08.pdf

 

3、人脸数据集

  • wider

参考论文:http://mmlab.ie.cuhk.edu.hk/projects/WIDERFace/support/paper.pdf

简述:32203张图,393703个人脸标签,包含了不同的规模,不同的姿势,不同的遮挡;

统一评测方法:随机40%训练集,10%验证集,50%测试集;

数据来源:Large Scale Ontology for Multimedia (LSCOM) 中的视频事件,谷歌、bing等搜索引擎,人工筛选(去掉不带有人脸的图)

 

 

4、人脸识别实现算法(深度学习)

1)人脸检测

MTCNN中提供了详细的检测人脸框与5个人脸关键点的配置与实现过程,但只是实现了人脸检测功能,实现结果如下:

2)人脸检测+人脸对齐

人脸对齐主要需要对人脸的各个部位进行矫正,MTCNN虽然提供了检测人脸5个关键点的方法,但没有提供人脸对齐(矫正)的方法。另外https://blog.csdn.net/zxj942405301/article/details/71799279提供了人脸对齐(矫正)的接口,我们可以借用一下,最终结果如下:

            ①原图                  ②对齐后

实现代码:

①参考上述博主中的链接:http://pan.baidu.com/s/1pLBGwuZ密码:fcyc

②Makefile文件+main.cpp,直接上代码吧!!!

Makefile:

# this is a makefile for caffe  
TARGET := classify  
# caffe directory  
CAFFE_DIR := $/caffe-master
# caffe include  
CAFFE_INCLUDE := $(CAFFE_DIR)/include
# caffe build   
CAFFE_BUILD := $(CAFFE_DIR)/build
# caffe build lib  
CAFFE_BUILD_LIB := $(CAFFE_BUILD)/lib  
# caffe build src  
CAFFE_BUILD_SRC := $(CAFFE_BUILD)/src  
 
# dependency libraries and caffe linking libs  
LFLAGS := -pthread -lnsl -lX11  
LFLAGS += -lcaffe -lglog -lgflags -lopencv_flann -lprotobuf -lboost_system -lboost_filesystem  -lboost_thread -lboost_coroutine -lboost_context -lboost_regex -lm -lhdf5_hl -lhdf5 -lleveldb -lsnappy -llmdb  -lopencv_core -lopencv_highgui -lopencv_imgproc -lopencv_objdetect -lstdc++ -lcblas -latlas  
 
LFLAGS += -Wl,-rpath=$(CAFFE_BUILD_LIB) -L/usr/lib/x86_64-linux-gnu/hdf5/serial
LFLAGS += -L/usr/local/lib -lopencv_core -lopencv_imgcodecs -lopencv_highgui
 
# rules  
CFLAGS := -g -I . -I $(CAFFE_INCLUDE) -I $(CAFFE_DIR)/src -I $(CAFFE_BUILD_SRC) -I/usr/include/hdf5/serial -I ./ -Wall -DCPU_ONLY -DUSE_OPENCV  
CC := g++  
 
SRC += main.cpp  MTCNN.cpp  #这里一定是所有的cpp文件
 
$(TARGET):$(SRC)  
	$(CC) -o $(TARGET) -O0 -std=c++11 $(SRC) $(CFLAGS) $(LFLAGS) -L$(CAFFE_BUILD_LIB) -Wno-sign-compare  
 
clean :  
	@rm -f $(TARGET) 

main.cpp

/*人脸检测、人脸对齐
主要代码:getFaceRects()
*/
#include <iostream>
#include "MTCNN.h"
#include <glob.h>
#include <vector>
#include <boost/algorithm/string.hpp>
using std::vector;

vector<string> globVector(const string& pattern){
    glob_t glob_result;
    glob(pattern.c_str(),GLOB_TILDE,NULL,&glob_result);
    vector<string> files;
    for(unsigned int i=0;i<glob_result.gl_pathc;++i){
        files.push_back(string(glob_result.gl_pathv[i]));
    }
    globfree(&glob_result);
    return files;
}
template <class T>
void ClearVector( vector<T>& vt ) 
{
    vector<T> veTemp; 
    veTemp.swap(vt);
}
int main(int argc, char const *argv[])
{
    /* code 批处理文件夹下所有的*.jpg文件,首先检测出人脸,再做人脸对齐(矫正-仿射变换)*/
    
    /*这是https://github.com/kpzhang93/MTCNN_face_detection_alignment/tree/master/code/codes/MTCNNv2/model
    中8个caffemodel、deploy文件所在目录路径*/
    const string& modelPath="$/MTCNN_face_detection_alignment/code/codes/MTCNNv2/model";
    
    string outputPath="$图像输出路径/";
    const string& imagePath = "$图像输入路径/*.jpg";
    vector<string> files = globVector(imagePath);//获取目录imagePath下所有*.jpg文件,存储到vector中,
    for (int i=0;i<files.size();i++)
    {
        cout<<files[i]<<endl;
        vector<string> tokens;
        boost::split(tokens, files[i], boost::is_any_of("/"));   
        cout<<tokens[tokens.size()-1]<<endl;
        vector<Mat> alignedFace;
        MTCNN mcnn = MTCNN(modelPath);
        Mat img = imread(files[i]);
        vector<Rect> faceRects;
        alignedFace = mcnn.getFaceRects(img, &faceRects);
        cout<<"**alignedFace.size=**"<<alignedFace.size()<<endl;
        int tempFaceRowId=0;
        int tempFaceColId=0;
        for (int j=0;j<alignedFace.size();j++)
        {
            // cout<<alignedFace[j].size()<<endl;
            if(tempFaceRowId<alignedFace[j].rows || tempFaceColId < alignedFace[j].cols)
            {
                imwrite(outputPath+tokens[tokens.size()-1],alignedFace[j]);
            }
            tempFaceRowId = alignedFace[j].rows;
            tempFaceColId = alignedFace[j].cols;
        }
        ClearVector(tokens);
        ClearVector(alignedFace);
        ClearVector(faceRects);
        cout<<"***this is a test***"<<endl;
    }
    // namedWindow("MyWindow", CV_WINDOW_NORMAL);
    // imshow("MyWindow", myImage);
    waitKey(0);
    // destroyWindow("MyWindow");
    return 0;
}

另外,gdb调试可能你会用到,调试方法可以参照博客:https://blog.csdn.net/lantuxin/article/details/80012111中第7点。

3)人脸识别

上述人脸检测、人脸对齐完成之后,人脸识别实际就是分类原理。

带遮挡的人脸识别框架参考网站:https://github.com/WeitaoVan/faceID#readme_caffe

具体实现过程:

①将对齐后的人脸放到face_example/data/中,可以分为train和val两个文件夹存储,并在data目录下生成train.txt和val.txt,可以参考https://blog.csdn.net/gaohuazhao/article/details/69568267

②修改solver和train_test相关的*.prototxt,主要是改其中的数据路径和最终分类类别。

补充说明:带遮挡的人脸识别框架参考网站中有一个错误很坑,一个x的参数写进了train_centerMask2Pool2_ori.prototxt中,不过删除就行了。

 

Logo

CSDN联合极客时间,共同打造面向开发者的精品内容学习社区,助力成长!

更多推荐