You are on page 1of 118

FACE RECOGNITION

TS NGUYỄN ĐỨC THÀNH 1


Các phương pháp nhận dạng khuôn mặt:
• EigenFace
• FisherFace
• Local Binary Patterns Histograms LBPH
• HOG +SVM
• Deep Learning

TS NGUYỄN ĐỨC THÀNH 2


PCA PHÂN TÍCH THÀNH PHẦN CHÍNH
• Vector đặc trưng x D chiều có thể giảm bớt số chiều bằng cách đưa
về vector đặc trưng y K<N chiều bằng cách chỉ giữ lại các đặc
trưng chính, như vậy việc tính toán sẽ nhanh hơn, đó là ý nghĩa của
phương pháp PCA.
• Cho dữ liệu gốc là vector x biểu diển trong không gian D chiều
thông qua hệ vector đơn vị e1...ud
x  x1e1  ..  xD e D
• Khi chuyển sang vector y biểu diển trong không gian K chiều thông
qua hệ vector đơn vị u1...uK
y  y1u1  ..  yK uK
• Tìm phép biến đổi tuyến tính y=Tx sao cho y biểu diển x với sai số
nhỏ nhất là mục tiêu của phương pháp PCA.
• Ví dụ nhận dạng ảnh khuôn mặt kích thước 100*100 pix tương
ứng với vector đặc trưng 10.000 chiều, ta có N ảnh mẫu khuôn mặt
một người và cần tìm xem một ảnh mới có trùng khớp với một
trong N ảnh mẫu
TS NGUYỄN ĐỨC THÀNH 3
PCA
• Một đứa trẻ vài tháng có thể nhận biết khuôn mặt của những người
thân quen mẹ, cha... Làm cách nào máy tính có thể nhận điện được
khuôn mặt đó là của ai trong cơ sở dữ liệu?
• Cho ảnh face, biểu diễn bởi vector cột xi trong không gian RD với
N ảnh ta tìm vector trung bình μ D chiều và ma trận hiệp phương
sai S D2 chiều
1 N 1 N
μ   xi , S   (xi  μ)( x j  μ)T
N i 1 N i , j 1

• Tính trị riêng λi và vector riêng νi D chiều của ma trận S thỏa mãn
công thức
Sνi  i νi , i  1..N
• Ma trận S vuông đối xứng có kích thước D2 khá lớn nên ta sẽ tìm
cách khác
TS NGUYỄN ĐỨC THÀNH 4
• Đặt X=[x1 -μ,x2 -μ...,xN- μ] ma trận D*N.
• Nhận xét rằng

S  XX T , XX T νi  i νi ,
X T X ( X T νi )  i ( X T νi ),

• Đặt ui=XT νi ta nhận thấy ui N chiều và λi lần lượt là vector riêng


và trị riêng của
Sr  X T X , X T Xui  i ui , XX T ( Xui )  i ( Xui )

có kích thước N2 nhỏ hơn rất nhiều so với D2


Sau khi tìm được ui ta tính νi=Xui , có N vector riêng νi kích thước
D. Vector xi ban đầu có thể biểu diễn trong không gian N chiều tạo
bởi N vector riêng νi
TS NGUYỄN ĐỨC THÀNH 5
PCA
νi
• Chuẩn hóa các vector riêng νi 
νi
• Tạo ma trận N hàng D cột V  [ν1T ; v2T ;..; v TN ]
• Ảnh xi ban đầu có kích thước D chiều biến đổi thành ảnh
yi = V(xi -μ) có kích thước N trong không gian tạo bời các vector
riêng vi
• Trong trường hợp N lớn ta có thể chọn K<N vector riêng có trị
riêng lớn nhất sắp xếp theo thứ tự giảm dần khác 0, K vector riêng
gọi là K thành phần chính.
• Như vậy một ảnh sẽ được biểu diển theo K thành phần chính gọi là
Eigenfaces.

TS NGUYỄN ĐỨC THÀNH 6


PCA MATLAB
clear all;
close all;
load yalefaces
[h,w,n] = size(yalefaces);
d = h*w;
% vectorize images
x = reshape(yalefaces,[d n]);
x = double(x);
%subtract mean
mean_matrix = mean(x,2);
x = bsxfun(@minus, x, mean_matrix);
% calculate covariance
s = cov(x');
% obtain eigenvalue & eigenvector
[V,D] = eig(s);
TS NGUYỄN ĐỨC THÀNH 7
PCA MATLAB
eigval = diag(D);
% sort eigenvalues in descending order
eigval = eigval(end:-1:1);
V = fliplr(V);
% show mean and 1th through 15th principal eigenvectors
figure,subplot(4,4,1)
imagesc(reshape(mean_matrix, [h,w]))
colormap gray
for i = 1:15
subplot(4,4,i+1)
imagesc(reshape(V(:,i),h,w))
end
TS NGUYỄN ĐỨC THÀNH 8
PCA MATLAB
% evaluate the number of principal components needed to represent
95% Total variance.
eigsum = sum(eigval);
csum = 0;
for i = 1:d
csum = csum + eigval(i);
tv = csum/eigsum;
if tv > 0.95
k95 = i;
break
end;
end;
TS NGUYỄN ĐỨC THÀNH 9
Nhận dạng khuôn mặt PCA
• Chuẩn bị tập ảnh huấn luyện gồm N ảnh chứa khuôn mặt của người
cần nhận dạng, có cùng kích thước r*c, mắt và miệng thẳng hàng
với nhau, cùng độ sáng, ảnh chứa thành vector cột xi có D=r*c
hàng , gồm các hàng ảnh nối tiếp nhau. Mọi ảnh tập huấn luyện
chứa trong ma trận X có N cột, D hàng.
• Tính ảnh trung bình μ, vector riêng chuẩn hóa vi và trị riêng λi của
ma trận covariance S
• Sắp xếp N trị riêng theo thứ tự giá trị giảm dần λ1, λ2 , λN ta chọn K
vector riêng lớn nhất và ngưỡng ε gần bằng 1 sao cho
K
• Biểu diễn ảnh trong tập huấn luyện theo K
 i
vector riêng yi = V(xi -μ) i 1

N
• Nhập ảnh mới face cần nhận dạng, biểu diển
theo không gian V: f = V(face -μ) . Tính khoảng
 i
i 1
cách giữa f và yi, gán ảnh cho khuôn mặt nào có khoảng cách nhỏ
nhất TS NGUYỄN ĐỨC THÀNH 10
FACE RECOGNIZER OPENCV 3.4.1
• Opencv 3.x không có sẵn module face, phải dùng opencv_contrib-
3.x cùng version với opencv 3.x
• Vào trang web để tìm bản contrib phù hợp
• https://github.com/opencv/opencv_contrib/releases
• Download và giải nén opencv_contrib-3.x
https://github.com/opencv/opencv_contrib/releases/tag/3.4.1
• Chạy cmake-gui.exe để build cac file dll và lib cho cac module
contrib

TS NGUYỄN ĐỨC THÀNH 11


FACE RECOGNIZER OPENCV 3.4.1
• Khi báo đường dẫn cho thư mục build và sources của opencv, khai
báo visual studio
• Bấm configure, generate, sau khi xong vào ô Search gõ tìm
OPENCV_EXTRA_MODULES_PATH
• Chỉ đường dẫn đến thư mục modules của opencv_contrib

• Bấm configure rồi generate. Nếu không có lỗi sẽ tạo file


OpenCV.sln trong thư mục build của opencv
• Mở Visual studio build OpenCV.sln để tạo lib trong thư mục
build/lib/Debug và dll trong build/bin/Debug để dùng trong các
project. Chép toàn bộ file dll build/bin/Debug sang x64/bin
TS NGUYỄN ĐỨC THÀNH 12
Philipp Wagner <bytefish[at]gmx[dot]de>
• opencv_contrib/modules/face/sample/facerec_eigenfaces.cpp
• https://docs.opencv.org/3.3.1/da/d60/tutorial_face_main.html
• Khởi tạo mô hình PCA
Ptr<FaceRecognizer> model = createEigenFaceRecognizer(); hay
Ptr<EigenFaceRecognizer> model = EigenFaceRecognizer::create();
• Dùng 10 thành phần chính: createEigenFaceRecognizer(10);
• Huấn luyện
model->train(images, labels);
• Kiểm tra
int predictedLabel = model->predict(testSample);
Hoặc Trả về nhãn và độ tin cậy
nt predictedLabel = -1;
double predicted_confidence = 0.0;
model->predict(testSample, predictedLabel, predicted_confidence);
TS NGUYỄN ĐỨC THÀNH 13
• Dùng thuật toán FisherFaces: ít phụ thuộc độ chiếu sáng
Ptr<FaceRecognizer> createFisherFaceRecognizer(int
num_components=0, double threshold=DBL_MAX); hay
Ptr<FisherFaceRecognizer> model = FisherFaceRecognizer::create();
• Dùng thuật toán LBPH
Ptr<FaceRecognizer> createLBPHFaceRecognizer(int radius=1, int
neighbors=8, int grid_x=8, int grid_y=8, double
threshold=DBL_MAX)
Ptr<LBPHFaceRecognizer> model = LBPHFaceRecognizer::
create();

TS NGUYỄN ĐỨC THÀNH 14


Cơ sở dữ liệu FACES
• Để chạy chương trình nhận dạng mặt cần chuẩn bị cơ sở dữ liệu
các khuôn mặt. Cơ sở dữ liệu có sẵn là AT&T database thuộc
phòng thí nghiệm AT&T Laboratories Cambridge
https://www.cl.cam.ac.uk/research/dtg/attarchive/facedatabase.html
• Tập ảnh chứa 10 khuôn mặt của 40 người, ảnh xám có kích
thước 112x92 pixels . Database gồm 40 folder s1..s40, mỗi thư
mục có 10 ảnh 1.pgm đến 10.pgm.

TS NGUYỄN ĐỨC THÀNH 15


EIGEN FACERECOGNITION
• Gỉa sử cần nhận dạng 10 người, ta sưu tập 100 ảnh mặt nhìn thẳng,
mỗi người 10 ảnh, có cùng kích thước, mắt và miệng các ảnh cùng
hàng với nhau. Đặt các ảnh trong thư mục tương tự ATT database

• Ví dụ: C:/faces/person0/image0.jpg,…,
C:/faces/person0/image9.jpg,
C:/faces/person1/image0.jpg,…, C:/faces/person9/image9.jpg,
Tạo file CSV (Comma Separated Values) face.txt ghi tên ảnh và
nhãn, theo từng dòng, có dạng như sau
/đường dẫn/person1/image0.jpg;0
/đường dẫn/person9/image9.jpg;9
TS NGUYỄN ĐỨC THÀNH 16
create_csv.py
• Ví dụ file ảnh trong thư mục d:/ATTDATABASE, dùng file
create_csv.py chạy trong python 3.6 như sau

TS NGUYỄN ĐỨC THÀNH 17


create_csv.py

TS NGUYỄN ĐỨC THÀNH 18


create_csv.py
• Trong cửa sổ command windows gõ python d:/create_csv.py
“d:/ATTDATABASE”, chương trình sẽ tạo file d:/face.txt như sau
d:/ATTDATABASE\s1/1.pgm;0
d:/ATTDATABASE\s1/10.pgm;0

d:/ATTDATABASE\s9/7.pgm;39
d:/ATTDATABASE\s9/8.pgm;39
d:/ATTDATABASE\s9/9.pgm;39
File sẽ dùng để khai báo cho chương trình read_csv

TS NGUYỄN ĐỨC THÀNH 19


OpenCV_Contrib/modules/
face/samples/etc/CropFace.py
• Chương trình chạy trên python dùng để sắp xếp các ảnh huấn luyện
có cùng kích thước, mắt và miệng thẳng hàng.

TS NGUYỄN ĐỨC THÀNH 20


FACE Recognition opencv c++
• Tạo project FaceRecognition, cài đặt property
• Linker Additional Dependencies, Additional Library Dependencies

TS NGUYỄN ĐỨC THÀNH 21


FACE Recognition opencv c++
• C/C++ General

TS NGUYỄN ĐỨC THÀNH 22


FACE Recognition opencv c++
• VC++ Directories

TS NGUYỄN ĐỨC THÀNH 23


FACEDETECT RECOGNITION/FaceRecognition.cpp
// FaceRecognition.cpp. Adapted from opencv_contrib/ modules/
face/samples/ facerec_eigenfaces.cpp
#include "stdafx.h"
#include "opencv2/opencv.hpp"
#include "opencv2/face/facerec.hpp"
#include <iostream>
#include <fstream>
#include <sstream>
using namespace cv;
using namespace cv::face;
using namespace std;

TS NGUYỄN ĐỨC THÀNH 24


FACEDETECT RECOGNITION/FaceRecognition.cpp
static Mat norm_0_255(InputArray _src) {
Mat src = _src.getMat();
// Create and return normalized image:
Mat dst;
switch (src.channels()) {
case 1:
cv::normalize(_src, dst, 0, 255, NORM_MINMAX, CV_8UC1);
break;
case 3:
cv::normalize(_src, dst, 0, 255, NORM_MINMAX, CV_8UC3);
break;
default:
src.copyTo(dst);
break;
}
return dst;
} TS NGUYỄN ĐỨC THÀNH 25
FACEDETECT RECOGNITION/FaceRecognition.cpp
static void read_csv(const string& filename, vector<Mat>& images,
vector<int>& labels, char separator = ';') {
std::ifstream file(filename.c_str(), ifstream::in);
string line, path, classlabel;
while (getline(file, line)) {
stringstream liness(line);
getline(liness, path, separator);
getline(liness, classlabel);
if (!path.empty() && !classlabel.empty()) {
images.push_back(imread(path, 0));
labels.push_back(atoi(classlabel.c_str()));
}
}
}
TS NGUYỄN ĐỨC THÀNH 26
FACEDETECT RECOGNITION/FaceRecognition.cpp
int main(int argc, const char *argv[]) {
vector<Mat> images;
vector<int> labels;
read_csv("d:/face.txt", images, labels);
// Get the height from the first image.
int height = images[0].rows;
//The last image is used for test
Mat testSample = images[images.size() - 1];
Mat dst;
int testLabel = labels[labels.size() - 1];
images.pop_back();
labels.pop_back();
TS NGUYỄN ĐỨC THÀNH 27
FACEDETECT RECOGNITION/FaceRecognition.cpp
// full PCA,
Ptr<EigenFaceRecognizer> model =
EigenFaceRecognizer::create();
model->train(images, labels);
int PredictedLabel = model->predict(testSample);
string result_message = format("Predicted class = %d / Actual class
= %d.", PredictedLabel, testLabel);
cout << result_message << endl;
// Here is how to get the eigenvalues of this Eigenfaces model:
Mat eigenvalues = model->getEigenValues();
Mat W = model->getEigenVectors();
// Get the sample mean from the training data
Mat mean = model->getMean();
Mat meanimg = norm_0_255(mean.reshape(1, images[0].rows));
hconcat(testSample, meanimg, dst);
imshow("Test Sample and Mean", dst);
TS NGUYỄN ĐỨC THÀNH 28
FACEDETECT RECOGNITION/FaceRecognition.cpp
// Display the Eigenfaces:
vector<Mat> dst1 (min(10, W.cols));
Mat dst2;
for (int i = 0; i < min(10, W.cols); i++) {
string msg = format("Eigenvalue #%d = %.5f", i,
eigenvalues.at<double>(i));
cout << msg << endl;
// get eigenface #i
Mat ef = W.col(i).clone();
// Reshape to original size & normalize to [0...255] for imshow.
Mat grayscale = norm_0_255(ef.reshape(1, height));
dst1[i] = grayscale;
}
hconcat(dst1, dst2);
imshow("EigenFaces", dst2);
waitKey(0);
return 0;
}
TS NGUYỄN ĐỨC THÀNH 29
FACEDETECT RECOGNITION/FaceRecognition.cpp

TS NGUYỄN ĐỨC THÀNH 30


FaceRec Video
• Giống chương trình trước, đọc camera, tách khuôn mặt rồi so sánh
với các khuôn mặt trong tập mẫu
// FaceRecognitionVideo.cpp : Defines the entry point for the console
application.
#include "stdafx.h"
#include "opencv2/opencv.hpp"
#include "opencv2/face.hpp"
#include <iostream>
#include <fstream>
#include <sstream>
using namespace cv;
using namespace cv::face;
using namespace std; TS NGUYỄN ĐỨC THÀNH 31
FaceRec Video
static void read_csv(const string& filename, vector<Mat>& images,
vector<int>& labels, char separator = ';') {
std::ifstream file(filename.c_str(), ifstream::in);
string line, path, classlabel;
while (getline(file, line)) {
stringstream liness(line);
getline(liness, path, separator);
getline(liness, classlabel);
if (!path.empty() && !classlabel.empty()) {
images.push_back(imread(path, 0));
labels.push_back(atoi(classlabel.c_str()));
}
}
}
TS NGUYỄN ĐỨC THÀNH 32
FaceRec Video
int main(int argc, const char *argv[]) {
vector<Mat> images;
vector<int> labels;
read_csv("d:/face.txt", images, labels);
int im_width = images[0].cols;
int im_height = images[0].rows;
// Create a FaceRecognizer and train it on the given images:
Ptr<LBPHFaceRecognizer> model =
LBPHFaceRecognizer::create();
model->train(images, labels);
CascadeClassifier haar_cascade;
haar_cascade.load("C:/opencv/sources/data/haarcascades/haar
cascade_frontalface_alt2.xml");
TS NGUYỄN ĐỨC THÀNH 33
FaceRec Video
// Get a handle to the Video device:
VideoCapture cap(0);
// Holds the current frame from the Video device:
Mat frame;
for (;;) {
cap >> frame;
// Clone the current frame:
Mat original = frame.clone();
// Convert the current frame to grayscale:
Mat gray;
cvtColor(original, gray, COLOR_BGR2GRAY);
// Find the faces in the frame:
vector< Rect_<int> > faces;
haar_cascade.detectMultiScale(gray, faces);
TS NGUYỄN ĐỨC THÀNH 34
FaceRec Video
for (size_t i = 0; i < faces.size(); i++) {
// Process face by face:
Rect face_i = faces[i];
// Crop the face from the image. So simple with OpenCV C++:
Mat face = gray(face_i);
Mat face_resized;
cv::resize(face, face_resized, Size(im_width, im_height), 1.0, 1.0,
INTER_CUBIC);
// Now perform the prediction, see how easy that is:
int prediction = model->predict(face_resized);
// And finally write all we've found out to the original image!
// First of all draw a green rectangle around the detected face:
rectangle(original, face_i, Scalar(0, 255, 0), 1);
// Create the text we will annotate the box with:
string box_text = format("Prediction = %d", prediction);
TS NGUYỄN ĐỨC THÀNH 35
FaceRec Video
// Calculate the position for annotated text (make sure we don't
// put illegal values in there):
int pos_x = std::max(face_i.tl().x - 10, 0);
int pos_y = std::max(face_i.tl().y - 10, 0);
// And now put it into the image:
putText(original, box_text, Point(pos_x, pos_y), FONT_HERSHEY_PLAIN, 1.0, Scalar(0, 255,
0), 2);
}
// Show the result:
imshow("face_recognizer", original);
// And display it:
char key = (char)waitKey(20);
// Exit this loop on escape:
if (key == 27)
break;
}
return 0;
}
TS NGUYỄN ĐỨC THÀNH 36
Linear Discriminant Analysis Fisherfaces

TS NGUYỄN ĐỨC THÀNH 37


LOCAL BINARY PATTERN HISTOGRAM LBPH(1996)
https://towardsdatascience.com/face-recognition-how-lbph-
works-90ec258c3d6b

• Phương pháp này trích xuất đặc trưng của ảnh bất biến với độ chiếu
sáng, tỷ lệ, tịnh tiến, quay.
• Dựa trên Local Binary Patterns xét 1 pixel với 8 điểm bao quanh,
so sánh cường độ điểm lân cận và pixel giữa, nếu nhỏ hơn ta thay
điểm lân cân cận bằng số 0, ngược lại thay bằng số 0. Như vậy ta
có số nhị phân 8 bit cho mỗi pixel không phụ thuộc vào độ chiếu
sáng. Tính toán cho toàn bột điểm ảnh ta có ảnh LBP, mỗi điểm
ảnh giá trị từ 0 đến 255

TS NGUYỄN ĐỨC THÀNH 38


LOCAL BINARY PATTERN HISTOGRAM LBPH(1996)

Thuật toán cải tiến dùng các cận trên vòng tròn bán kính R, vậy
có hai tham số là bán kính R thường là 1 và số lân cận thường là
8

TS NGUYỄN ĐỨC THÀNH 39


TS NGUYỄN ĐỨC THÀNH 40
LOCAL BINARY PATTERN HISTOGRAM LBPH(1996)

• Áp dụng histogram cho ảnh LBP, ta chia ảnh thành các cell theo
chiều X và Y, gridX và gridY là số cell chiều X và chiều Y, tạo
vector histogram cho mỗi cell, sau đó ghép với nhau ta được vector
histogram cho toàn ảnh, chính là đặc trưng của ảnh.
• So sánh khoảng cách vector đặc trưng ảnh cần nhận dạng với ảnh
huấn luyện, ta gán nhãn dựa trên khoảng cách nhỏ hơn.
• Confidence là thông số khoảng cách, nếu confidence=0.0 kết quả
nhận dạng là chính xác.
• Thông thường ta đặt ngưỡng threshold, nếu confidence<threshold
thì công nhận kết quả phân lớp. Phân lớp cũng có thể dùng SVM
hoặc KNN.
TS NGUYỄN ĐỨC THÀNH 41
LOCAL BINARY PATTERN HISTOGRAM LBPH(1996)

Ví dụ ảnh LBP có 9 cell, dùng số lân cận là P=8, mỗi cell biểu thị
bằng histogram chiều dại 256 có giá trị là số pixel cùng cường độ.
Histogram toàn ảnh là vector dài 9*236. Con số này rất lớn.
Giảm kích thước của vector histogram mỗi cell bằng cách chỉ xét các
pixel kế nhau tạo thành uniform pattern nghia là có nhiều nhất hai
chuyển tiếp từ 0 sang 1 hay ngược lại ví dụ như 00000000, 00011110
10000011, 11111110...
TS NGUYỄN ĐỨC THÀNH 42
LOCAL BINARY PATTERN HISTOGRAM LBPH(1996)
• 58 uniform binary patterns tương ứng các số 0, 1, 2, 3, 4, 6, 7, 8,
12, 14, 15, 16, 24, 28, 30, 31, 32, 48, 56, 60, 62, 63, 64, 96, 112,
120, 124, 126, 127, 128, 129, 131, 135, 143, 159, 191, 192, 193,
195, 199, 207, 223, 224, 225, 227, 231, 239, 240, 241, 243, 247,
248, 249, 251, 252, 253, 254 và 255.
• Vị trí còn lại cho các mẫu khác, vậy chiều dài vector đặc trưng mỗi
cell là P*(P-1)+3 thay vì 2P . Tại sao?
• Nếu khảo sát thêm phép bất biến quay, hai vector quay trái hay
phải là giống nhau như vậy các số 1, 2, 4, 8, 16, 32, 64,128 gom
thành bin 1. Có thể chứng minh là số bin với uniform pattern và
rotation invariant giảm còn P+2?. Với 8 lân cận số bin là 10: (0),
(255), (1,2,4,8,16,32,64,128), (3,6,12,24,48,96,129,192),
(7,14,28,56,112,131,193,240), (15,30,60,120,135,195,215,240),
(31,62,124,227,248,249), (63,126,243,249,250, 252), (các số còn
lại)
TS NGUYỄN ĐỨC THÀNH 43
FACRECOGNIZER OPENCV C++ LBPH
• Opencv_contrib/modules/face/samples/facerec_lbph.cpp
• https://docs.opencv.org/3.0-
beta/modules/face/doc/facerec/facerec_tutorial.html#local-binary-
patterns-histograms
// FaceRecognition.cpp : Defines the entry point for the console
application.
//Adapted from opencv_contrib/modules/face/samples/facerec_lbph.cpp
#include "stdafx.h"
#include "opencv2/opencv.hpp"
#include "opencv2/face.hpp"
#include <iostream>
#include <fstream>
#include <sstream>
using namespace cv;
using namespace cv::face;
using namespace std;
TS NGUYỄN ĐỨC THÀNH 44
FACRECOGNIZER OPENCV C++ LBPH
static Mat norm_0_255(InputArray _src) {…}
static void read_csv(const string& filename, vector<Mat>& images,
vector<int>& labels, char separator = ';') {…]
int main(int argc, const char *argv[]) {
vector<Mat> images;
vector<int> labels;
read_csv("d:/face.txt", images, labels);
// Get the height from the first image.
int height = images[0].rows;
//The last image is used for test
Mat testSample = images[images.size() - 1];
Mat dst;
int testLabel = labels[labels.size() - 1];
images.pop_back();
labels.pop_back();
TS NGUYỄN ĐỨC THÀNH 45
FACRECOGNIZER OPENCV C++ LBPH
Ptr<LBPHFaceRecognizer> model =
LBPHFaceRecognizer::create();
model->train(images, labels);
model->setThreshold( 0.0);
int PredictedLabel = model->predict(testSample);
string result_message = format("Predicted class = %d / Actual
class = %d.", PredictedLabel, testLabel);
cout << result_message << endl;
cout << "Model Information:" << endl; string
model_info = format("LBPH(radius= %i, neighbors= %i, grid_x=
%i, grid_y= %i, threshold= % 0.2f)",
model->getRadius(),
model->getNeighbors(),
model->getGridX(),
TS NGUYỄN ĐỨC THÀNH 46
FACRECOGNIZER OPENCV C++ LBPH
model->getGridY(),
model->getThreshold());
cout << model_info << endl;
// We could get the histograms for example:
vector<Mat> histograms = model->getHistograms(); //
Probably the length is interesting:
cout << "Size of the histograms: " << histograms[0].total() <<
endl;return 0;
}
Bấm Control F5

TS NGUYỄN ĐỨC THÀNH 47


FaceRec Python
#Khởi tạo mô hình
face_recognizer = cv2.face.LBPHFaceRecognizer_create()
face_recognizer = cv2.face.EigenFaceRecognizer_create()
face_recognizer = cv2.face.FisherFaceRecognizer_create()
#Huấn luyện
face_recognizer.train(trainingfaces, np.array(labels))
#Nhận dạng
label, confidence = face_recognizer.predict(testface)
#Sưu tập bộ ảnh các nhân vật muốn nhận dạng, mỗi ảnh chỉ có một
nhân vật, đầy đủ khuôn mặt, các ảnh lưu vào thư mục riêng si cho
mỗi nhân vật thứ i, ảnh trong thư mục được đặt tên ví dụ j.jpg. Tất cả
đặt vào thư mục training image
#Tạo thư mục Recognition image chứa các ảnh nhân vật không nằm
trong training image
TS NGUYỄN ĐỨC THÀNH 48
FaceRec Python
• Dùng cascade classifier luyện tập ảnh training image tách khuôn
mặt, tạo tập ảnh khuôn mặt xám có cùng kích thước và được gán
nhãn.
• Huấn luyện PCA dùng face_recognizer.train
• Cho ảnh kiểm tra trong test image vào, tách khuôn mặt rồi dùng
hàm face_recognizer.train gán nhãn cho ảnh

TS NGUYỄN ĐỨC THÀNH 49


FaceRec Python

TS NGUYỄN ĐỨC THÀNH 50


FaceRec Python

TS NGUYỄN ĐỨC THÀNH 51


FaceRec Python

TS NGUYỄN ĐỨC THÀNH 52


FaceRec Python

TS NGUYỄN ĐỨC THÀNH 53


FaceRec Python

TS NGUYỄN ĐỨC THÀNH 54


TS NGUYỄN ĐỨC THÀNH 55
TS NGUYỄN ĐỨC THÀNH 56
FaceRec Python

TS NGUYỄN ĐỨC THÀNH 57


FaceRec Python

TS NGUYỄN ĐỨC THÀNH 58


FaceRec Python

TS NGUYỄN ĐỨC THÀNH 59


FACE DETECT DEEP LEARNING
• Kỹ thuật deep learning dùng trong face detection, face recognition
có độ chính xác cao hơn các phương pháp cổ truyền, có thể phát
giác khuôn mặt nhìn nghiêng, bị khuất…
• Thường dùng mạng đã được huấn luyện như “res10_300x300_ssd
_ iter_140000.caffemodel” sử dụng ảnh kích thước 300*300. Nếu
không bạn sẽ tốn rất nhiều thời gian để train mạng của riêng bạn!.
• Đi kèm với caffemodel là file deploy.prototxt mô tả mạng
• Tìm trong thư mục opencv
c:\opencv\sources\samples\dnn\face_detector\deploy.prototxt
• https://www.pyimagesearch.com/2018/02/26/face-detection-with-
opencv-and-deep-learning/
• Download 2 file vào máy

TS NGUYỄN ĐỨC THÀNH 60


FACE DETECT DNN PYTHON HÀM DNN OPENCV
• readNetFromCaffe()
Net cv::dnn::readNetFromCaffe(const String & prototxt,
const String & caffeModel = String() )
Net cv::dnn::readNetFromCaffe(const char * bufferProto, size_t
lenProto, const char * bufferModel = NULL, size_t lenModel = 0 )
Net cv::dnn::readNetFromCaffe(const std::vector< uchar > &
bufferProto,
const std::vector< uchar > & bufferModel = std::vector< uchar >()
)
Python:
retval =cv.dnn.readNetFromCaffe(prototxt[, caffeModel] )
retval =cv.dnn.readNetFromCaffe(bufferProto[, bufferModel] )
Khi đọc mạng đã được huấn luyện từ framework caffe dùng hai đối
số, thứ nhất là file text có đuôi prototxt mô tả cấu trúc mạng, thứ hai
là file có đuôi caffemodel chứa vector trọng số
TS NGUYỄN ĐỨC THÀNH 61
readNet()
Net cv::dnn::readNet (const String & model, const String &
config = "", const String & framework = "" )
Python:
retval =cv.dnn.readNet(model[, config[, framework]])
retval =cv.dnn.readNet(framework, bufferModel[, bufferConfig] )
Parameters
[in] model Binary file contains trained weights. The following
file extensions are expected for models from different frameworks:
*.caffemodel (Caffe, http://caffe.berkeleyvision.org/)
*.pb (TensorFlow, https://www.tensorflow.org/)
*.t7 | *.net (Torch, http://torch.ch/)
*.weights (Darknet, https://pjreddie.com/darknet/)
TS NGUYỄN ĐỨC THÀNH 62
*.bin (DLDT, https://software.intel.com/openvino-toolkit)
[in] config Text file contains network configuration. It could be a
file with the following extensions:
*.prototxt (Caffe, http://caffe.berkeleyvision.org/)
*.pbtxt (TensorFlow, https://www.tensorflow.org/)
*.cfg (Darknet, https://pjreddie.com/darknet/)
*.xml (DLDT, https://software.intel.com/openvino-toolkit)
[in] framework Explicit framework name tag to determine a
format.
Returns
Net object.

TS NGUYỄN ĐỨC THÀNH 63


FACE DETECT DNN PYTHON HÀM DNN OPENCV
• Ảnh nhận dạng được tiền xử lý trước khi đưa vào mạng dùng hàm
blobFromImage() tạo 4-dimensional blob từ ảnh.
void cv::dnn::blobFromImage(InputArray image, OutputArray
blob, double scalefactor = 1.0, const Size & size = Size(), const
Scalar & mean = Scalar(), bool swapRB = false, bool crop = false, int
ddepth = CV_32F )
• Python:
retval=cv.dnn.blobFromImage(image[, scalefactor[, size[, mean[,
swapRB[, crop[, ddepth]]]]]])
• Parameters:
images: input images (all with 1-, 3- or 4-channels)
size: spatial size for output image
mean: scalar with mean values which are subtracted from channels.
Values are intended to be in (mean-R, mean-G, mean-B) order if
image has BGR ordering and swapRB is true.
TS NGUYỄN ĐỨC THÀNH 64
FACE DETECT DNN PYTHON HÀM DNN OPENCV
scalefactor: multiplier for images values.
swapRB: flag which indicates that swap first and last channels in 3-
channel image is necessary.
crop: flag which indicates whether image will be cropped after resize
or not
ddepth: Depth of output blob. Choose CV_32F or CV_8U.
if crop is true, input image is resized so one side after resize is equal
to corresponding dimension in size and another one is equal or larger.
Then, crop from the center is performed. If crop is false, direct resize
without cropping and preserving aspect ratio is performed.
Return: 4 dimensional MAT with NCHW dimensions order. N: size
of blob, C number of channel, for color it is 3, H: Height, W: width

TS NGUYỄN ĐỨC THÀNH 65


FACE DETECT DNN PYTHON HÀM DNN OPENCV
• Before we begin training our deep neural network, we first compute the
average pixel intensity across all images in the training set for each of the
Red, Green, and Blue channels. This implies that we end up with three
variables: mu_R, mu_G, and mu_B. Typically the resulting values are a
3-tuple consisting of the mean of the Red, Green, and Blue channels,
respectively. For example, the mean values for the ImageNet training set
are R=103.93, G=116.77, and B=123.68.
• When we are ready to pass an image through our network (whether for
training or testing), we subtract the mean, \mu, from each input channel
of the input image:
R = R - mu_R, G = G - mu_G, B = B - mu_B
We may also have a scaling factor, \sigma, which adds in a normalization:
R = (R - mu_R) /sigma
G = (G - mu_G) /sigma
B = (B - mu_B) /sigma
TS NGUYỄN ĐỨC THÀNH 66
blobFromImages()
void cv::dnn::blobFromImages(InputArrayOfArrays images,
OutputArray blob, double scalefactor = 1.0, Size size = Size(),
const Scalar & mean = Scalar(), bool swapRB = false, bool crop =
false, int ddepth = CV_32F )
Python:
retval =cv.dnn.blobFromImages(images[, scalefactor[, size[, mean[,
swapRB[, crop[, ddepth]]]]]] )

TS NGUYỄN ĐỨC THÀNH 67


FACE DETECT DNN PYTHON
• Sử dụng mạng đã huấn luyện caffemodel với ảnh 300x300
• https://www.pyimagesearch.com/2018/02/26/face-detection-with-opencv-
and-deep-learning/
• deep-learning-face-detection/ adapted_detect_faces.py
import numpy as np
import cv2
# load our serialized model from disk
net = cv2.dnn.readNetFromCaffe("deploy.prototxt.txt",
"res10_300x300_ssd_iter_140000.caffemodel")
# load the input image and construct an input blob for the image
# by resizing to a fixed 300x300 pixels and then normalizing it
image = cv2.imread("rooster.jpg")
(h, w) = image.shape[:2]
blob = cv2.dnn.blobFromImage(cv2.resize(image, (300, 300)), 1.0,
(300, 300), (104.0, 177.0, 123.0))
TS NGUYỄN ĐỨC THÀNH 68
# pass the blob through the network and obtain the detections and predictions
net.setInput(blob)
detections = net.forward()
# loop over the detections
for i in range(0, detections.shape[2]):
# extract the confidence (i.e., probability) associated with the prediction
confidence = detections[0, 0, i, 2]
# filter out weak detections by ensuring the `confidence` is
# greater than the minimum confidence
if confidence > 0.5:
# compute the (x, y)-coordinates of the bounding box for the
# object
box = detections[0, 0, i, 3:7] * np.array([w, h, w, h])
(startX, startY, endX, endY) = box.astype("int")
TS NGUYỄN ĐỨC THÀNH 69
FACE DETECT DNN PYTHON
# draw the bounding box of the face along with the
#associated probability
text = "{:.2f}%".format(confidence * 100)
y = startY - 10 if startY - 10 > 10 else startY + 10
cv2.rectangle(image, (startX, startY), (endX, endY),
(0, 0, 255), 2)
cv2.putText(image, text, (startX, y),
cv2.FONT_HERSHEY_SIMPLEX, 0.45, (0, 0,
255), 2)

# show the output image


cv2.imshow("Output", image)
cv2.waitKey(0)
cv2.destroyAllWindows()
TS NGUYỄN ĐỨC THÀNH 70
FACE DETECT DNN PYTHON

TS NGUYỄN ĐỨC THÀNH 71


FACE DETECT DNN PYTHON

TS NGUYỄN ĐỨC THÀNH 72


FACE DETECT CAMERA DNN PYTHON
• deep-learning-face-detection/ adapted_detect_faces_video.py
import numpy as np
from cv2 import *
net = dnn.readNetFromCaffe("deploy.prototxt.txt",
"res10_300x300_ssd_iter_140000.caffemodel")
while True:
cap = VideoCapture(0)
ret, frame = cap.read()
(h, w) = frame.shape[:2]
h=int(w*h/400)
frame = resize(frame,(h,400) )
(h, w) = frame.shape[:2]
blob = dnn.blobFromImage(resize(frame, (300, 300)), 1.0,
(300, 300), (104.0, 177.0, 123.0))
TS NGUYỄN ĐỨC THÀNH 73
FACE DETECT CAMERA DNN PYTHON
net.setInput(blob)
detections = net.forward()
for i in range(0, detections.shape[2]):
confidence = detections[0, 0, i, 2]
if confidence < 0.5:
continue
box = detections[0, 0, i, 3:7] * np.array([w, h, w, h])
(startX, startY, endX, endY) = box.astype("int")
text = "{:.2f}%".format(confidence * 100)
y = startY - 10 if startY - 10 > 10 else startY + 10
rectangle(frame, (startX, startY), (endX, endY),
(0, 0, 255), 2)
TS NGUYỄN ĐỨC THÀNH 74
FACE DETECT CAMERA DNN PYTHON
putText(frame, text, (startX, y),
FONT_HERSHEY_SIMPLEX, 0.45, (0, 0, 255), 2)
imshow("Frame", frame)
key = waitKey(1) & 0xFF
# if the `q` key was pressed, break from the loop
if key == ord("q"):
break
destroyAllWindows()
cap.release()

TS NGUYỄN ĐỨC THÀNH 75


FACE RECOGNITION DNN
• DNN giúp nâng cao độ chính xác nhận dạng khuôn mặt của một
người, nổi bật nhất lá FaceNet và DeepFace
• FaceNet ánh xạ ảnh khuôn mặt vào không gian vector đặc trưng
128 chiều, các vector đặc trưng của cùng một người có khoảng
cách gần nhau, còn các vector đặc trưng của hai người khác nhau
có khoảng cách xa hơn. FaceNet được nghiên cứu bởi công ty
Google: Florian Schroff, Dmitry Kalenichenko, James Philbin
trong bài báo FaceNet: A Unified Embedding for Face Recognition
and Clustering.
• Sử dụng mạng CNN, đầu vào huấn luyện là bộ ba ảnh gồm ảnh neo
anchor, ảnh dương của củng một người và ảnh âm của người khác,
bộ huấn luyện sẽ tìm vector đặc trưng 128 chiều sao cho khoảng
cách giữa ảnh anchor và ảnh dương cùng một người xa hơn khoảng
cách giữa ảnh anchor và ảnh âm

TS NGUYỄN ĐỨC THÀNH 76


TS NGUYỄN ĐỨC THÀNH 77
FACE RECOGNITION DNN

TS NGUYỄN ĐỨC THÀNH 78


FACE RECOGNITION DNN

TS NGUYỄN ĐỨC THÀNH 79


FACE RECOGNITION DNN

Cực tiểu hàm tổn thất triplet loss L bằng cách huấn luyện hàm f

• FaceNet huấn luyện với một số lượng lớn hình ảnh (hơn 200 triệu
ảnh của 8 triệu đối tượng). Deepface do nhóm nghiên cứu
Facebook phát triển, dùng mạng DNN 9 lớp và huấn luyện 4 triệu
ảnh với độ chính xác 97%.
• OpenFace is a deep learning facial recognition model developed
by Brandon Amos, Bartosz Ludwiczuk, and Mahadev
Satyanarayanan. It’s based off of the paper: FaceNet: A Unified
Embedding for Face Recognition and Clustering and is
implemented using Python and Torch so it can be run on CPU or
GPU’s.
TS NGUYỄN ĐỨC THÀNH 80
OpenFace Dlib
https://blog.algorithmia.com/understanding-facial-recognition-
openface/
"Openface: A general-purpose face recognition library with mobile
applications,“Brandon Amos, Bartosz Ludwiczuk, Mahadev
Satyanarayanan
From a high level perspective, OpenFace uses Torch, a scientific
computing framework to do training offline, meaning it’s only done
once by OpenFace and the user doesn’t have to get their hands dirty
training hundreds of thousands of images themselves. Those images
are then thrown into a neural net for feature extraction using Google’s
FaceNet model. FaceNet relies on a triplet loss function to compute
the accuracy of the neural net classifying a face and is able to cluster
faces because of the resulting measurements on a hypersphere.
This trained neural net is later used in the Python implementation after
new images are run through dlib’s face detection model. Once the
faces are normalized by OpenCV’s Affine transformation so all faces
are pointing in the same direction, they are sent through the trained
neural net in a single forward pass. This results in 128 facial
embeddings used for classification for matching or can even used in a
clustering algorithm for similarity detection.
TS NGUYỄN ĐỨC THÀNH 81
OpenFace Dlib

TS NGUYỄN ĐỨC THÀNH 82


OpenFace Dlib
During the training portion of the OpenFace pipeline, 500k images
are passed through the neural net. These images are from two public
datasets: CASIA-WebFace which is comprised of 10,575 indiviudals
with a total of 494,414 images and FaceScrub which is made of 530
individuals with a total of 106,863 images who are public figures.
The point of training the neural net on all these images ahead of time
is that obviously, it wouldn’t be possible on mobile or any other real-
time scenario to train 500,000 images to retrieve the needed facial
embeddings. Now remember, this portion of the pipeline is only done
once because OpenFace trains these images to produce 128 facial
embeddings that represent a generic face that are to be later used in
the Python training-on-the-fly part of the pipeline. Then instead of
matching an image in high-dimensional space, you’re only using
low-dimensional data which helps make this model fast.

TS NGUYỄN ĐỨC THÀNH 83


OpenFace Dlib
As mentioned before, OpenFace uses Google’s FaceNet architecture
for feature extraction and uses a triplet loss function to test how
accurate the neural net classifies a face. It does this by training on
three different images where one is a known face image called the
anchor image, then another image of that same person has positive
embeddings, while the last one is an image of a different person
which of course has negative embeddings.
The cool thing about using triple embeddings is that the embeddings
are measured on a unit hypersphere where Euclidean distance is used
to determine which images are closer together and which ones are
further apart. Obviously, the negative image embeddings are
measured further from the positive and anchor embeddings while
those two would be closer in distance to each other. This is important
because it allows for clustering algorithms to be used for similarity
detection. You might want to use a clustering algorithm if you
wanted to detect family members on a genealogy site for example, or
on social media for possible marketing campaigns
TS NGUYỄN ĐỨC THÀNH 84
OpenFace Dlib
Face detect: One of the first steps in facial recognition software is to
isolate the actual face from the background of the image along with
isolating each face from others found in the image. Face detection
algorithms also must be able to deal with bad and inconsistent
lighting and various facial positions such as tilted or rotated faces.
Luckily dlib along with OpenCV handles all these issues. Dlib takes
care of finding the fiducial points on the face while OpenCV handles
the normalization of the facial position.
It’s important to note that while using OpenFace you can either
implement dlib for face detection, which uses a combination of HOG
(Histogram of Oriented Gradient) & Support Vector Machine or
OpenCV’s Haar cascade classifier. Both are trained on positive and
negative images (meaning there are images that have faces and ones
that don’t), but they are very different in implementation, speed, and
accuracy.
TS NGUYỄN ĐỨC THÀNH 85
OpenFace Dlib
There are several benefits to using the HOG classifier. First, the training is
done using a sliding sub-window on the image so no subsampling and
parameter manipulation is required like it is in Haar classifier that is used in
OpenCV. This makes dlib’s HOG and SVM face detection easier to use and
faster to train. It also means that less data is required and note that HOG
has higher accuracy for face detection than OpenCV’s Haar cascade
classifier. Kind of makes using dlib’s HOG + SVM a no brainer for face
detection!
Preprocessing: Along with finding each face in an image, part of the
process in facial recognition is preprocessing the images to handle
problems such as inconsistent and bad lighting, converting images to
grayscale for faster training, and normalization of facial position.
While some facial recognition models can handle these issues by training
on massive datasets, dlib uses OpenCV’s 2D Affine transformation which
rotates the face and makes the position of the eyes, nose, and mouth for
each face consistent. There are 68 facial landmarks used in affine
transformation for feature detection and the distances between those points
are measured and compared to the points found in an average face image.
Then the image is rotated and transformed based on those points to
normalize the face for comparison and cropped to 96×96 pixels for input to
the trained neural net.
TS NGUYỄN ĐỨC THÀNH 86
OpenFace Dlib

TS NGUYỄN ĐỨC THÀNH 87


OpenFace Dlib
Classification: So, after we isolate the image from the background
and preprocess it using dlib and OpenCV, we can pass the image into
the trained neural net that was done in the Torch portion of the
pipeline. In this step, there is a single forward pass on the neural net
to get 128 embeddings (facial features) that are used in prediction.
These low-dimensional facial embeddings are then used in
classification or clustering algorithms.
For classification in tests OpenFace uses a linear support vector
machine which is commonly used out in the real world to match
image features. The most impressive thing about OpenFace, that at
this point it takes only a few milliseconds to classify images.

TS NGUYỄN ĐỨC THÀNH 88


OpenFace Dlib

TS NGUYỄN ĐỨC THÀNH 89


Face_Recognition
• Cài đặt dlib: dlib is a modern C++ toolkit containing machine learning
algorithms and tools for creating complex software in C++ to solve real
world problems. It is used in both industry and academia in a wide range of
domains including robotics, embedded devices, mobile phones, and large
high performance computing environments.
pip install dlib
or
workon <your env name here> # optional
git clone https://github.com/davisking/dlib.git
cd dlib
mkdir build
cd build
cmake .. -DUSE_AVX_INSTRUCTIONS=1
cmake --build .
cd ..
python setup.py install --yes USE_AVX_INSTRUCTIONS
TS NGUYỄN ĐỨC THÀNH 90
OPENCV FACE RECOGNITION PYTHON
• https://www.pyimagesearch.com/2018/09/24/opencv-face-
recognition/
• opencv-face-recognition\recognize.py
• Dùng mạng FaceNet đã dược huấn luyện, huấn luyện thêm cho
tập ảnh mới:
• Detect faces
• Compute 128-d face embeddings to quantify a face
• Train a Support Vector Machine (SVM) on top of the
embeddings
• Recognize faces in images and video streams

TS NGUYỄN ĐỨC THÀNH 91


TS NGUYỄN ĐỨC THÀNH 92
dataset/ : Contains our face images organized into subfolders by name.
images/ : Contains three test images that we’ll use to verify the operation of
our model.
face_detection_model/ : Contains a pre-trained Caffe deep learning model
provided by OpenCV to detect faces. This model detects and localizes faces
in an image.
output/ : Contains my output pickle files. If you’re working with your own
dataset, you can store your output files here as well. The output files
include:
embeddings.pickle : A serialized facial embeddings file. Embeddings have
been computed for every face in the dataset and are stored in this file.
le.pickle : Our label encoder. Contains the name labels for the people that
our model can recognize.
recognizer.pickle : Our Linear Support Vector Machine (SVM) model. This
is a machine learning model rather than a deep learning model and it is
responsible for actually recognizing faces.
TS NGUYỄN ĐỨC THÀNH 93
extract_embeddings.py : this file is responsible for using a deep
learning feature extractor to generate a 128-D vector describing a
face. All faces in our dataset will be passed through the neural
network to generate embeddings.
openface_nn4.small2.v1.t7 : A Torch deep learning model which
produces the 128-D facial embeddings..
train_model.py : Our Linear SVM model will be trained by this
script. We’ll detect faces, extract embeddings, and fit our SVM
model to the embeddings data.
recognize.py : recognize faces in images. We’ll detect faces, extract
embeddings, and query our SVM model to determine who is in an
image. We’ll draw boxes around faces and annotate each box with a
name.
recognize_video.py : recognize who is in frames of a video stream
TS NGUYỄN ĐỨC THÀNH 94
Face detect: dùng mô hình mạng
"res10_300x300_ssd_iter_140000.caffemodel“
protoPath = os.path.sep.join(["face_detection_model",
"deploy.prototxt"])
modelPath = os.path.sep.join(["face_detection_model",
"res10_300x300_ssd_iter_140000.caffemodel"])
detector = cv2.dnn.readNetFromCaffe(protoPath, modelPath)
Face recognition: dùng openface
embedder =
cv2.dnn.readNetFromTorch("openface_nn4.small2.v1.t7")
recognizer = pickle.loads(open("output/recognizer.pickle",
"rb").read())
le = pickle.loads(open("output/le.pickle", "rb").read())
TS NGUYỄN ĐỨC THÀNH 95
ADAPTED EXTRACT EMBEDDING.PY
#extract embedding then save to disk
#opencv-face-recognition/ adapted_extract_embeddings.py
# import the necessary packages
from imutils import paths
import numpy as np
import imutils
import pickle
import cv2
import os
detector =
cv2.dnn.readNetFromCaffe("face_detection_model/deploy.prototxt",
"face_detection_model/res10_300x300_ssd_iter_140000.caffemodel
") TS NGUYỄN ĐỨC THÀNH 96
ADAPTED EXTRACT EMBEDDING.PY
embedder =
cv2.dnn.readNetFromTorch("openface_nn4.small2.v1.t7")
imagePaths = list(paths.list_images("dataset"))
# initialize our lists of extracted facial embeddings and
# corresponding people names
knownEmbeddings = []
knownNames = []
# initialize the total number of faces processed
total = 0
# loop over the image paths
for (i, imagePath) in enumerate(imagePaths):
# extract the person name from the image path
name = imagePath.split(os.path.sep)[-2]
TS NGUYỄN ĐỨC THÀNH 97
ADAPTED EXTRACT EMBEDDING.PY
# load the image, resize it to have a width of 600 pixels (while
# maintaining the aspect ratio), and then grab the image
# dimensions
image = cv2.imread(imagePath)
image = imutils.resize(image, width=600)
(h, w) = image.shape[:2]
# construct a blob from the image
imageBlob = cv2.dnn.blobFromImage(
cv2.resize(image, (300, 300)), 1.0, (300, 300),
(104.0, 177.0, 123.0), swapRB=False, crop=False)
# apply OpenCV's deep learning-based face detector to localize
# faces in the input image
detector.setInput(imageBlob)
detections = detector.forward()
TS NGUYỄN ĐỨC THÀNH 98
ADAPTED EXTRACT EMBEDDING.PY
# ensure at least one face was found
if len(detections) > 0:
# we're making the assumption that each image has only ONE
# face, so find the bounding box with the largest probability
i = np.argmax(detections[0, 0, :, 2])
confidence = detections[0, 0, i, 2]
# ensure that the detection with the largest probability also
# means our minimum probability test (thus helping filter out
# weak detections)
if confidence > 0.5:
# compute the (x, y)-coordinates of the bounding box
#for the face
box = detections[0, 0, i, 3:7] * np.array([w, h, w, h])
(startX, startY, endX, endY) = box.astype("int")

TS NGUYỄN ĐỨC THÀNH 99


ADAPTED EXTRACT EMBEDDING.PY
# extract the face ROI and grab the ROI dimensions
face = image[startY:endY, startX:endX]
(fH, fW) = face.shape[:2]
# ensure the face width and height are
#sufficiently large
if fW < 20 or fH < 20:
continue
# construct a blob for the face ROI, then pass
#the blob
# through our face embedding model to obtain
#the 128-d quantification of the face
faceBlob = cv2.dnn.blobFromImage(face, 1.0 /
255, (96, 96), (0, 0, 0), swapRB=True, crop=False)
TS NGUYỄN ĐỨC THÀNH 100
ADAPTED EXTRACT EMBEDDING.PY
embedder.setInput(faceBlob)
vec = embedder.forward()
# add the name of the person + corresponding face
# embedding to their respective lists
knownNames.append(name)
knownEmbeddings.append(vec.flatten())
total += 1
# save the facial embeddings + names to disk
data = {"embeddings": knownEmbeddings, "names": knownNames}
f = open("output/embeddings.pickle", "wb")
f.write(pickle.dumps(data))
f.close()
print("Extract_embedding_DONE")
TS NGUYỄN ĐỨC THÀNH 101
Adapted train_model.py
#Train SVM model face recognition use embedding vertor
#opencv-face-recognition/adapted train_model.py
from sklearn.preprocessing import LabelEncoder
from sklearn.svm import SVC
import pickle
# load the face embeddings
data = pickle.loads(open("output/embeddings.pickle", "rb").read())
# encode the labels
le = LabelEncoder()
labels = le.fit_transform(data["names"])

TS NGUYỄN ĐỨC THÀNH 102


Adapted train_model.py
# train the SVN model used to accept the 128-d embeddings of the face and
# then produce the actual face recognition
recognizer = SVC(C=1.0, kernel="linear", probability=True)
recognizer.fit(data["embeddings"], labels)
# write the actual face recognition model to disk
f = open("output/recognizer.pickle", "wb")
f.write(pickle.dumps(recognizer))
f.close()
# write the label encoder to disk
f = open("output/le.pickle", "wb")
f.write(pickle.dumps(le))
f.close()
print("Save SVM recognition model to disk, DONE")
TS NGUYỄN ĐỨC THÀNH 103
Adapted recognize.py
#d:/opencv-face-recognition/adapted recognize.py
#use SVM from trainmodel.py
#use opencv dnn
import numpy as np
import imutils
import pickle
import cv2
# load our serialized face detector from disk
detector =
cv2.dnn.readNetFromCaffe("face_detection_model/deploy.prototxt",
"face_detection_model/res10_300x300_ssd_iter_140000.caffemodel
")
TS NGUYỄN ĐỨC THÀNH 104
OPENCV FACE RECOGNITION PYTHON
# load our serialized face embedding model from disk
embedder =
cv2.dnn.readNetFromTorch("openface_nn4.small2.v1.t7")
# load the actual face recognition model SVM along with the label
encoder
recognizer = pickle.loads(open("output/recognizer.pickle",
"rb").read())
le = pickle.loads(open("output/le.pickle", "rb").read())
# load the image, resize it to have a width of 600 pixels (while
# maintaining the aspect ratio), and then grab the image dimensions
image = cv2.imread("images/trisha_adrian.jpg ")
image = imutils.resize(image, width=600)
(h, w) = image.shape[:2] TS NGUYỄN ĐỨC THÀNH 105
OPENCV FACE RECOGNITION PYTHON
# construct a blob from the image
imageBlob = cv2.dnn.blobFromImage(
cv2.resize(image, (300, 300)), 1.0, (300, 300),
(104.0, 177.0, 123.0), swapRB=False, crop=False)

# apply OpenCV's deep learning-based face detector to localize


# faces in the input image
detector.setInput(imageBlob)
detections = detector.forward()
# loop over the detections
for i in range(0, detections.shape[2]):
# extract the confidence (i.e., probability) associated with the
# prediction
confidence = detections[0, 0, i, 2]
TS NGUYỄN ĐỨC THÀNH 106
OPENCV FACE RECOGNITION PYTHON
# filter out weak detections
if confidence > 0.5:
# compute the (x, y)-coordinates of the bounding box
box = detections[0, 0, i, 3:7] * np.array([w, h, w, h])
(startX, startY, endX, endY) = box.astype("int")
# extract the face ROI
face = image[startY:endY, startX:endX]
(fH, fW) = face.shape[:2]
# ensure the face width and height are sufficiently large
if fW < 20 or fH < 20:
continue
# construct a blob for the face ROI, then pass the blob
# through our face embedding model to obtain the 128-d
# quantification of the face
TS NGUYỄN ĐỨC THÀNH 107
OPENCV FACE RECOGNITION PYTHON
faceBlob = cv2.dnn.blobFromImage(face, 1.0 / 255, (96,
96), (0, 0, 0), swapRB=True, crop=False)
embedder.setInput(faceBlob)
vec = embedder.forward()
# perform classification to recognize the face
preds = recognizer.predict_proba(vec)[0]
j = np.argmax(preds)
proba = preds[j]
name = le.classes_[j]
# draw the bounding box of the face along with the
#associated probability
text = "{}: {:.2f}%".format(name, proba * 100)
TS NGUYỄN ĐỨC THÀNH 108
OPENCV FACE RECOGNITION PYTHON
y = startY - 10 if startY - 10 > 10 else startY + 10
cv2.rectangle(image, (startX, startY), (endX, endY),
(0, 0, 255), 2)
cv2.putText(image, text, (startX, y),
cv2.FONT_HERSHEY_SIMPLEX, 0.45, (0,
0, 255), 2)
# show the output image
cv2.imshow("Recognized Image", image)
cv2.waitKey(0)
cv2.destroyAllWindows()

TS NGUYỄN ĐỨC THÀNH 109


OPENCV FACE RECOGNITION PYTHON

TS NGUYỄN ĐỨC THÀNH 110


FACE_ RECOGNITION DNN
• Gói phần mềm nhận dạng https://pypi.org/project/face_recognition/
• Cài đặt: pip install face_recognition
• Recognize and manipulate faces from Python or from the command
line with the world’s simplest face recognition library.
• Built using dlib’s state-of-the-art face recognition, built with deep
learning. The model has an accuracy of 99.38% on the Labeled
Faces in the Wild benchmark.

TS NGUYỄN ĐỨC THÀNH 111


FACE RECOGNITION OPENCV PYTHON
https://www.pyimagesearch.com/2018/06/18/face-recognition-with-
opencv-python-and-deep-learning/
• Use face_recognition package
• Detect face using model “cnn” or “hog”
boxes = face_recognition.face_locations(rgb,model="cnn")
• Get facial embeddings
encodings = face_recognition.face_encodings(rgb, boxes)
• Find matches, compare encoding
matches =
face_recognition.compare_faces(data["encodings"],encoding)
• In folder dataset we have image of many subject, each subject in a
folder. See https://www.pyimagesearch.com/2018/04/09/how-to-
quickly-build-a-deep-learning-image-dataset/ to know how to
download image using Bing Image
TS NGUYỄN Search API,
ĐỨC THÀNH 112
TS NGUYỄN ĐỨC THÀNH 113
FACE RECOGNITION OPENCV PYTHON
import face_recognition
import pickle
import cv2
# load the known faces and embeddings
data = pickle.loads(open("encodings.pickle", "rb").read())
image = cv2.imread("d:/face-recognition-
opencv/examples/example_03.png")
rgb = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
#detect face and returm 128d embedding for each face
#model "hog" or "cnn", hog is faster
boxes = face_recognition.face_locations(rgb,model="hog")
encodings = face_recognition.face_encodings(rgb, boxes)
TS NGUYỄN ĐỨC THÀNH 114
FACE RECOGNITION OPENCV PYTHON
# initialize the list of names for each face detected
names = []
# loop over the facial embeddings
for encoding in encodings:
# attempt to match each face in the input image to our known
#encodings
matches =
face_recognition.compare_faces(data["encodings"],encoding)
name = "Unknown"
# check to see if we have found a match
if True in matches:
# find the indexes of all matched faces then initialize a
# dictionary to count the total number of times each face
# was matched
matchedIdxs = [i for (i, b) in enumerate(matches) if b]
counts = {}
TS NGUYỄN ĐỨC THÀNH 115
FACE RECOGNITION OPENCV PYTHON
# loop over the matched indexes and maintain a count
#for each recognized face face
for i in matchedIdxs:
name = data["names"][i]
counts[name] = counts.get(name, 0) + 1
# determine the recognized face with the largest
#number of votes (in #the event of an unlikely tie
#Python will select first entry in the dictionary)
name = max(counts, key=counts.get)

# update the list of names


names.append(name)

TS NGUYỄN ĐỨC THÀNH 116


FACE RECOGNITION OPENCV PYTHON
# loop over the recognized faces
for ((top, right, bottom, left), name) in zip(boxes, names):
# draw the predicted face name on the image
cv2.rectangle(image, (left, top), (right, bottom), (0, 255, 0), 2)
y = top - 15 if top - 15 > 15 else top + 15
cv2.putText(image, name, (left, y),
cv2.FONT_HERSHEY_SIMPLEX, 0.75, (0, 255, 0), 2)

cv2.imshow(""Recognized Image"", image)


print("done, press any key to close windows")
cv2.waitKey(0)
cv2.destroyAllWindows()
TS NGUYỄN ĐỨC THÀNH 117
FACE RECOGNITION OPENCV PYTHON

TS NGUYỄN ĐỨC THÀNH 118

You might also like