欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

人脸识别

程序员文章站 2022-07-14 15:33:15
...

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

人脸识别系统:

1)人脸检测:检测出人脸在图像中的大小和位置,libfacedetection(ShiqiYu),seetaface(ShiguangShan),深度学习

2)人脸对齐:将人脸变换到统一的角度和姿态,对人脸关键点进行相似变换(旋转,缩放,平移),尽可能转换到标准人脸

3)人脸特征表示:向量化人脸特征,分类器判别人脸识别结果。

论文地址: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、人脸数据集

1)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中,不过删除就行了。