2016年11月23日星期三

Deep Face Recognition with Caffe Implementation

This branch is developed for deep face recognition, the related paper is as follows.
A Discriminative Feature Learning Approach for Deep Face Recognition[C]
Yandong Wen, Kaipeng Zhang, Zhifeng Li*, Yu Qiao
European Conference on Computer Vision. Springer International Publishing, 2016: 499-515.
https://github.com/ydwen/caffe-face 

Updates

  • Oct 13, 2016
    • A demo for extracting deep feature by the given model is provided.
  • Oct 12, 2016
  • Otc 9, 2016
    • The code and training prototxt for our ECCV16 paper are released.
    • If you train our Network on CAISA-WebFace, the expected verification performance of SINGLE MODEL on LFW should be ~99%.

Files

  • Original Caffe library
  • Center Loss
    • src/caffe/proto/caffe.proto
    • include/caffe/layers/center_loss_layer.hpp
    • src/caffe/layers/center_loss_layer.cpp
    • src/caffe/layers/center_loss_layer.cu
  • face_example
    • face_example/data/
    • face_example/face_snapshot/
    • face_example/face_train_test.prototxt
    • face_example/face_solver.prototxt
    • face_example/face_deploy.prototxt
    • face_example/extractDeepFeature.m
  • mnist_example
    • mnist_example/data/
    • mnist_example/face_snapshot/
    • mnist_example/mnist_train_test.prototxt
    • mnist_example/mnist_solver.prototxt
    • mnist_example/mnist_deploy.prototxt

Train_Model

  1. The Installation completely the same as Caffe. Please follow the installation instructions. Make sure you have correctly installed before using our code.
  2. Download the face dataset for training, e.g. CAISA-WebFace, VGG-Face, MS-Celeb-1M, MegaFace.
  3. Preprocess the training face images, including detection, alignment, etc. Here we strongly recommend MTCNN, which is an effective and efficient open-source tool for face detection and alignment.
  4. Creat list for training set and validation set. Place them in face_example/data/
  5. Specify your data source for train & val
    layer {
      name: "data"
      type: "ImageData"
      top: "data"
      top: "label"
      image_data_param {
        source: "face_example/data/###your_list###"
      }
    }
    
  6. Specify the number of subject in FC6 layer
    layer {
      name: "fc6"
      type: "InnerProduct"
      bottom: "fc5"
      top: "fc6"
      inner_product_param {
        num_output: ##number##
      }
    }
    
  7. Specify the loss weight and the number of subject in center loss layer
    layer {
      name: "center_loss"
      type: "CenterLoss"
      bottom: "fc5"
      bottom: "label"
      top: "center_loss"
      loss_weight: ##weight##
      center_loss_param {
        num_output: ##number##
      }
    }
    
  8. Train model
    cd $CAFFE-FACE_ROOT
    ./build/tools/caffe train -solver face_example/face_solver.prototxt -gpu X,Y
    

Extract_DeepFeature

  1. Compile matcaffe by make matcaffe
  2. Specify the correspinding paths in face_example/extractDeepFeature.m
    addpath('path_to_matCaffe/matlab');
    model = 'path_to_deploy/face_deploy.prototxt';
    weights = 'path_to_model/face_model.caffemodel';
    image = imread('path_to_image/Jennifer_Aniston_0016.jpg');
    
  3. Run extractDeepFeature.m in Matlab

Contact

Citation

You are encouraged to cite the following paper if it helps your research.
@inproceedings{wen2016discriminative,
  title={A Discriminative Feature Learning Approach for Deep Face Recognition},
  author={Wen, Yandong and Zhang, Kaipeng and Li, Zhifeng and Qiao, Yu},
  booktitle={European Conference on Computer Vision},
  pages={499--515},
  year={2016},
  organization={Springer}
}

License

Copyright (c) Yandong Wen
All rights reserved.
MIT License
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

2016年7月21日星期四

OpenFace: an open source facial behavior analysis toolkit

OpenFace: an open source facial behavior analysis toolkit

from:https://github.com/TadasBaltrusaitis/OpenFace
Over the past few years, there has been an increased interest in automatic facial behavior analysis and understanding. We present OpenFace – an open source tool intended for computer vision and machine learning researchers, affective computing community and people interested in building interactive applications based on facial behavior analysis. OpenFace is the first open source tool capable of facial landmark detection, head pose estimation, facial action unit recognition, and eye-gaze estimation. The computer vision algorithms which represent the core of OpenFace demonstrate state-of-the-art results in all of the above mentioned tasks. Furthermore, our tool is capable of real-time performance and is able to run from a simple webcam without any specialist hardware.
The code was written mainly by Tadas Baltrusaitis during his time at the Language Technologies Institute at the Carnegie Mellon University; Computer Laboratory, University of Cambridge; and Institute for Creative Technologies, University of Southern California.
Special thanks goes to Louis-Philippe Morency and his MultiComp Lab at Institute for Creative Technologies for help in writing and testing the code, and Erroll Wood for the gaze estimation work.
For instructions of how to install/compile/use the project please see wiki

Functionality

The system is capable of performing a number of facial analysis tasks:
  • Facial Landmark Detection
Sample facial landmark detection image
  • Facial Landmark and head pose tracking (links to YouTube videos)
Multiple Face Tracking Multiple Face Tracking
  • Facial Action Unit Recognition
  • Gaze tracking (image of it in action)
  • Facial Feature Extraction (aligned faces and HOG features)
Sample aligned face and HOG image

Citation

If you use any of the resources provided on this page in any of your publications we ask you to cite the following work and the work for a relevant submodule you used.

Overall system

OpenFace: an open source facial behavior analysis toolkit Tadas Baltrušaitis, Peter Robinson, and Louis-Philippe Morency, inIEEE Winter Conference on Applications of Computer Vision, 2016

Facial landmark detection and tracking

Constrained Local Neural Fields for robust facial landmark detection in the wild Tadas Baltrušaitis, Peter Robinson, and Louis-Philippe Morency. in IEEE Int. Conference on Computer Vision Workshops, 300 Faces in-the-Wild Challenge, 2013.

Eye gaze tracking

Rendering of Eyes for Eye-Shape Registration and Gaze Estimation Erroll Wood, Tadas Baltrušaitis, Xucong Zhang, Yusuke Sugano, Peter Robinson, and Andreas Bulling in IEEE International. Conference on Computer Vision (ICCV), 2015

Facial Action Unit detection

Cross-dataset learning and person-specific normalisation for automatic Action Unit detection Tadas Baltrušaitis, Marwa Mahmoud, and Peter Robinson in Facial Expression Recognition and Analysis ChallengeIEEE International Conference on Automatic Face and Gesture Recognition, 2015

Final remarks

I did my best to make sure that the code runs out of the box but there are always issues and I would be grateful for your understanding that this is research code and not a commercial level product. However, if you encounter any problems/bugs/issues please contact me on github or by emailing me at Tadas.Baltrusaitis@cl.cam.ac.uk for any bug reports/questions/suggestions.

Copyright

Copyright can be found in the Copyright.txt
You have to respect boost, TBB, dlib, and OpenCV licenses.

2016年7月4日星期一

ResNet-18

from:https://github.com/beniz/deepdetect/blob/master/templates/caffe/resnet_18/resnet_18.prototxt


name: "ResNet-18" layer {
name: "resnet_18"
type: "Data"
top: "data"
top: "label"
include {
phase: TRAIN
}
transform_param {
mirror: true
crop_size: 224
mean_file: "mean.binaryproto"
}
data_param {
source: "train.lmdb"
batch_size: 32
backend: LMDB
}
}
layer {
name: "resnet_18"
type: "MemoryData"
top: "data"
top: "label"
include {
phase: TEST
}
memory_data_param {
batch_size: 32
channels: 3
height: 224
width: 224
}
}
layer {
name: "conv1"
type: "Convolution"
bottom: "data"
top: "conv1"
convolution_param {
num_output: 64
pad: 3
kernel_size: 7
stride: 2
weight_filler {
type: "xavier"
}
bias_filler {
type: "constant"
value: 0.2
}
}
}
layer {
name: "bn_conv1"
type: "BatchNorm"
bottom: "conv1"
top: "conv1"
batch_norm_param {
}
}
layer {
name: "scale_conv1"
type: "Scale"
bottom: "conv1"
top: "conv1"
scale_param {
bias_term: true
}
}
layer {
name: "conv1_relu"
type: "ReLU"
bottom: "conv1"
top: "conv1"
}
layer {
name: "pool1"
type: "Pooling"
bottom: "conv1"
top: "pool1"
pooling_param {
pool: MAX
kernel_size: 3
stride: 2
}
}
layer {
name: "res2a_branch1"
type: "Convolution"
bottom: "pool1"
top: "res2a_branch1"
convolution_param {
num_output: 256
bias_term: false
pad: 0
kernel_size: 1
stride: 1
weight_filler {
type: "xavier"
}
bias_filler {
type: "constant"
value: 0.2
}
}
}
layer {
name: "bn2a_branch1"
type: "BatchNorm"
bottom: "res2a_branch1"
top: "res2a_branch1"
batch_norm_param {
}
}
layer {
name: "scale2a_branch1"
type: "Scale"
bottom: "res2a_branch1"
top: "res2a_branch1"
scale_param {
bias_term: true
}
}
layer {
name: "res2a_branch2a"
type: "Convolution"
bottom: "pool1"
top: "res2a_branch2a"
convolution_param {
num_output: 64
bias_term: false
pad: 0
kernel_size: 1
stride: 1
weight_filler {
type: "xavier"
}
bias_filler {
type: "constant"
value: 0.2
}
}
}
layer {
name: "bn2a_branch2a"
type: "BatchNorm"
bottom: "res2a_branch2a"
top: "res2a_branch2a"
batch_norm_param {
}
}
layer {
name: "scale2a_branch2a"
type: "Scale"
bottom: "res2a_branch2a"
top: "res2a_branch2a"
scale_param {
bias_term: true
}
}
layer {
name: "res2a_branch2a_relu"
type: "ReLU"
bottom: "res2a_branch2a"
top: "res2a_branch2a"
}
layer {
name: "res2a_branch2b"
type: "Convolution"
bottom: "res2a_branch2a"
top: "res2a_branch2b"
convolution_param {
num_output: 64
bias_term: false
pad: 1
kernel_size: 3
stride: 1
weight_filler {
type: "xavier"
}
bias_filler {
type: "constant"
value: 0.2
}
}
}
layer {
name: "bn2a_branch2b"
type: "BatchNorm"
bottom: "res2a_branch2b"
top: "res2a_branch2b"
batch_norm_param {
}
}
layer {
name: "scale2a_branch2b"
type: "Scale"
bottom: "res2a_branch2b"
top: "res2a_branch2b"
scale_param {
bias_term: true
}
}
layer {
name: "res2a_branch2b_relu"
type: "ReLU"
bottom: "res2a_branch2b"
top: "res2a_branch2b"
}
layer {
name: "res2a_branch2c"
type: "Convolution"
bottom: "res2a_branch2b"
top: "res2a_branch2c"
convolution_param {
num_output: 256
bias_term: false
pad: 0
kernel_size: 1
stride: 1
weight_filler {
type: "xavier"
}
bias_filler {
type: "constant"
value: 0.2
}
}
}
layer {
name: "bn2a_branch2c"
type: "BatchNorm"
bottom: "res2a_branch2c"
top: "res2a_branch2c"
batch_norm_param {
}
}
layer {
name: "scale2a_branch2c"
type: "Scale"
bottom: "res2a_branch2c"
top: "res2a_branch2c"
scale_param {
bias_term: true
}
}
layer {
name: "res2a"
type: "Eltwise"
bottom: "res2a_branch1"
bottom: "res2a_branch2c"
top: "res2a"
}
layer {
name: "res2a_relu"
type: "ReLU"
bottom: "res2a"
top: "res2a"
}
layer {
name: "res2b_branch2a"
type: "Convolution"
bottom: "res2a"
top: "res2b_branch2a"
convolution_param {
num_output: 64
bias_term: false
pad: 0
kernel_size: 1
stride: 1
weight_filler {
type: "xavier"
}
bias_filler {
type: "constant"
value: 0.2
}
}
}
layer {
name: "bn2b_branch2a"
type: "BatchNorm"
bottom: "res2b_branch2a"
top: "res2b_branch2a"
batch_norm_param {
}
}
layer {
name: "scale2b_branch2a"
type: "Scale"
bottom: "res2b_branch2a"
top: "res2b_branch2a"
scale_param {
bias_term: true
}
}
layer {
name: "res2b_branch2a_relu"
type: "ReLU"
bottom: "res2b_branch2a"
top: "res2b_branch2a"
}
layer {
name: "res2b_branch2b"
type: "Convolution"
bottom: "res2b_branch2a"
top: "res2b_branch2b"
convolution_param {
num_output: 64
bias_term: false
pad: 1
kernel_size: 3
stride: 1
weight_filler {
type: "xavier"
}
bias_filler {
type: "constant"
value: 0.2
}
}
}
layer {
name: "bn2b_branch2b"
type: "BatchNorm"
bottom: "res2b_branch2b"
top: "res2b_branch2b"
batch_norm_param {
}
}
layer {
name: "scale2b_branch2b"
type: "Scale"
bottom: "res2b_branch2b"
top: "res2b_branch2b"
scale_param {
bias_term: true
}
}
layer {
name: "res2b_branch2b_relu"
type: "ReLU"
bottom: "res2b_branch2b"
top: "res2b_branch2b"
}
layer {
name: "res2b_branch2c"
type: "Convolution"
bottom: "res2b_branch2b"
top: "res2b_branch2c"
convolution_param {
num_output: 256
bias_term: false
pad: 0
kernel_size: 1
stride: 1
weight_filler {
type: "xavier"
}
bias_filler {
type: "constant"
value: 0.2
}
}
}
layer {
name: "bn2b_branch2c"
type: "BatchNorm"
bottom: "res2b_branch2c"
top: "res2b_branch2c"
batch_norm_param {
}
}
layer {
name: "scale2b_branch2c"
type: "Scale"
bottom: "res2b_branch2c"
top: "res2b_branch2c"
scale_param {
bias_term: true
}
}
layer {
name: "res2b"
type: "Eltwise"
bottom: "res2a"
bottom: "res2b_branch2c"
top: "res2b"
}
layer {
name: "res2b_relu"
type: "ReLU"
bottom: "res2b"
top: "res2b"
}
layer {
name: "res2c_branch2a"
type: "Convolution"
bottom: "res2b"
top: "res2c_branch2a"
convolution_param {
num_output: 64
bias_term: false
pad: 0
kernel_size: 1
stride: 1
weight_filler {
type: "xavier"
}
bias_filler {
type: "constant"
value: 0.2
}
}
}
layer {
name: "bn2c_branch2a"
type: "BatchNorm"
bottom: "res2c_branch2a"
top: "res2c_branch2a"
batch_norm_param {
}
}
layer {
name: "scale2c_branch2a"
type: "Scale"
bottom: "res2c_branch2a"
top: "res2c_branch2a"
scale_param {
bias_term: true
}
}
layer {
name: "res2c_branch2a_relu"
type: "ReLU"
bottom: "res2c_branch2a"
top: "res2c_branch2a"
}
layer {
name: "res2c_branch2b"
type: "Convolution"
bottom: "res2c_branch2a"
top: "res2c_branch2b"
convolution_param {
num_output: 64
bias_term: false
pad: 1
kernel_size: 3
stride: 1
weight_filler {
type: "xavier"
}
bias_filler {
type: "constant"
value: 0.2
}
}
}
layer {
name: "bn2c_branch2b"
type: "BatchNorm"
bottom: "res2c_branch2b"
top: "res2c_branch2b"
batch_norm_param {
}
}
layer {
name: "scale2c_branch2b"
type: "Scale"
bottom: "res2c_branch2b"
top: "res2c_branch2b"
scale_param {
bias_term: true
}
}
layer {
name: "res2c_branch2b_relu"
type: "ReLU"
bottom: "res2c_branch2b"
top: "res2c_branch2b"
}
layer {
name: "res2c_branch2c"
type: "Convolution"
bottom: "res2c_branch2b"
top: "res2c_branch2c"
convolution_param {
num_output: 256
bias_term: false
pad: 0
kernel_size: 1
stride: 1
weight_filler {
type: "xavier"
}
bias_filler {
type: "constant"
value: 0.2
}
}
}
layer {
name: "bn2c_branch2c"
type: "BatchNorm"
bottom: "res2c_branch2c"
top: "res2c_branch2c"
batch_norm_param {
}
}
layer {
name: "scale2c_branch2c"
type: "Scale"
bottom: "res2c_branch2c"
top: "res2c_branch2c"
scale_param {
bias_term: true
}
}
layer {
name: "res2c"
type: "Eltwise"
bottom: "res2b"
bottom: "res2c_branch2c"
top: "res2c"
}
layer {
name: "res2c_relu"
type: "ReLU"
bottom: "res2c"
top: "res2c"
}
layer {
name: "res3a_branch1"
type: "Convolution"
bottom: "res2c"
top: "res3a_branch1"
convolution_param {
num_output: 512
bias_term: false
pad: 0
kernel_size: 1
stride: 2
weight_filler {
type: "xavier"
}
bias_filler {
type: "constant"
value: 0.2
}
}
}
layer {
name: "bn3a_branch1"
type: "BatchNorm"
bottom: "res3a_branch1"
top: "res3a_branch1"
batch_norm_param {
}
}
layer {
name: "scale3a_branch1"
type: "Scale"
bottom: "res3a_branch1"
top: "res3a_branch1"
scale_param {
bias_term: true
}
}
layer {
name: "res3a_branch2a"
type: "Convolution"
bottom: "res2c"
top: "res3a_branch2a"
convolution_param {
num_output: 128
bias_term: false
pad: 0
kernel_size: 1
stride: 2
weight_filler {
type: "xavier"
}
bias_filler {
type: "constant"
value: 0.2
}
}
}
layer {
name: "bn3a_branch2a"
type: "BatchNorm"
bottom: "res3a_branch2a"
top: "res3a_branch2a"
batch_norm_param {
}
}
layer {
name: "scale3a_branch2a"
type: "Scale"
bottom: "res3a_branch2a"
top: "res3a_branch2a"
scale_param {
bias_term: true
}
}
layer {
name: "res3a_branch2a_relu"
type: "ReLU"
bottom: "res3a_branch2a"
top: "res3a_branch2a"
}
layer {
name: "res3a_branch2b"
type: "Convolution"
bottom: "res3a_branch2a"
top: "res3a_branch2b"
convolution_param {
num_output: 128
bias_term: false
pad: 1
kernel_size: 3
stride: 1
weight_filler {
type: "xavier"
}
bias_filler {
type: "constant"
value: 0.2
}
}
}
layer {
name: "bn3a_branch2b"
type: "BatchNorm"
bottom: "res3a_branch2b"
top: "res3a_branch2b"
batch_norm_param {
}
}
layer {
name: "scale3a_branch2b"
type: "Scale"
bottom: "res3a_branch2b"
top: "res3a_branch2b"
scale_param {
bias_term: true
}
}
layer {
name: "res3a_branch2b_relu"
type: "ReLU"
bottom: "res3a_branch2b"
top: "res3a_branch2b"
}
layer {
name: "res3a_branch2c"
type: "Convolution"
bottom: "res3a_branch2b"
top: "res3a_branch2c"
convolution_param {
num_output: 512
bias_term: false
pad: 0
kernel_size: 1
stride: 1
weight_filler {
type: "xavier"
}
bias_filler {
type: "constant"
value: 0.2
}
}
}
layer {
name: "bn3a_branch2c"
type: "BatchNorm"
bottom: "res3a_branch2c"
top: "res3a_branch2c"
batch_norm_param {
}
}
layer {
name: "scale3a_branch2c"
type: "Scale"
bottom: "res3a_branch2c"
top: "res3a_branch2c"
scale_param {
bias_term: true
}
}
layer {
name: "res3a"
type: "Eltwise"
bottom: "res3a_branch1"
bottom: "res3a_branch2c"
top: "res3a"
}
layer {
name: "res3a_relu"
type: "ReLU"
bottom: "res3a"
top: "res3a"
}
layer {
name: "res3b_branch2a"
type: "Convolution"
bottom: "res3a"
top: "res3b_branch2a"
convolution_param {
num_output: 128
bias_term: false
pad: 0
kernel_size: 1
stride: 1
weight_filler {
type: "xavier"
}
bias_filler {
type: "constant"
value: 0.2
}
}
}
layer {
name: "bn3b_branch2a"
type: "BatchNorm"
bottom: "res3b_branch2a"
top: "res3b_branch2a"
batch_norm_param {
}
}
layer {
name: "scale3b_branch2a"
type: "Scale"
bottom: "res3b_branch2a"
top: "res3b_branch2a"
scale_param {
bias_term: true
}
}
layer {
name: "res3b_branch2a_relu"
type: "ReLU"
bottom: "res3b_branch2a"
top: "res3b_branch2a"
}
layer {
name: "res3b_branch2b"
type: "Convolution"
bottom: "res3b_branch2a"
top: "res3b_branch2b"
convolution_param {
num_output: 128
bias_term: false
pad: 1
kernel_size: 3
stride: 1
weight_filler {
type: "xavier"
}
bias_filler {
type: "constant"
value: 0.2
}
}
}
layer {
name: "bn3b_branch2b"
type: "BatchNorm"
bottom: "res3b_branch2b"
top: "res3b_branch2b"
batch_norm_param {
}
}
layer {
name: "scale3b_branch2b"
type: "Scale"
bottom: "res3b_branch2b"
top: "res3b_branch2b"
scale_param {
bias_term: true
}
}
layer {
name: "res3b_branch2b_relu"
type: "ReLU"
bottom: "res3b_branch2b"
top: "res3b_branch2b"
}
layer {
name: "res3b_branch2c"
type: "Convolution"
bottom: "res3b_branch2b"
top: "res3b_branch2c"
convolution_param {
num_output: 512
bias_term: false
pad: 0
kernel_size: 1
stride: 1
weight_filler {
type: "xavier"
}
bias_filler {
type: "constant"
value: 0.2
}
}
}
layer {
name: "bn3b_branch2c"
type: "BatchNorm"
bottom: "res3b_branch2c"
top: "res3b_branch2c"
batch_norm_param {
}
}
layer {
name: "scale3b_branch2c"
type: "Scale"
bottom: "res3b_branch2c"
top: "res3b_branch2c"
scale_param {
bias_term: true
}
}
layer {
name: "res3b"
type: "Eltwise"
bottom: "res3a"
bottom: "res3b_branch2c"
top: "res3b"
}
layer {
name: "res3b_relu"
type: "ReLU"
bottom: "res3b"
top: "res3b"
}
layer {
name: "pool5"
type: "Pooling"
bottom: "res3b"
top: "pool5"
pooling_param {
pool: AVE
kernel_size: 7
stride: 1
}
}
layer {
name: "fc1000"
type: "InnerProduct"
bottom: "pool5"
top: "fc1000"
inner_product_param {
num_output: 5
weight_filler {
type: "xavier"
}
bias_filler {
type: "constant"
value: 0
}
}
}
layer {
name: "prob"
type: "SoftmaxWithLoss"
bottom: "fc1000"
bottom: "label"
top: "prob"
include {
phase: TRAIN
}
}
layer {
name: "probt"
type: "Softmax"
bottom: "fc1000"
top: "probt"
include {
phase: TEST
}
}