前面一篇文章講了Dlib的人臉關(guān)鍵點(diǎn)提取: http://www.itdecent.cn/p/5a49c157fd88
提取的關(guān)鍵點(diǎn)可以用于各種任務(wù)。
此外Dlib 提供了一個(gè)face embedding功能,簡(jiǎn)單來(lái)說就是將人臉編碼為128維向量,這個(gè)向量可以用來(lái)分類,聚類,相似度計(jì)算等等。Python 包 face_recognition提供了Dlib C++特征提取的Python封裝,這里我們使用這個(gè)接口來(lái)進(jìn)行特征提取,然后進(jìn)行幾個(gè)簡(jiǎn)單的分類任務(wù)試驗(yàn),一個(gè)是性別分類,一個(gè)是微笑表情分類。
數(shù)據(jù)集介紹
這里我們使用的數(shù)據(jù)集是CelebA, CelebA是一個(gè)人臉屬性分類數(shù)據(jù)集,包含來(lái)自于10k個(gè)名人的200k圖像,每張圖片有40個(gè)臉部屬性,5個(gè)角點(diǎn)信息,包含配準(zhǔn)和沒有配準(zhǔn)的的數(shù)據(jù)。
https://www.cv-foundation.org/openaccess/content_iccv_2015/papers/Liu_Deep_Learning_Face_ICCV_2015_paper.pdf

數(shù)據(jù)準(zhǔn)備
Dlib人臉特征提取
先安裝python face_recognition 模塊:
pip3 install face_recognition
使用方法,調(diào)用face_recognition 的 face_encodings 模塊:
face_embedding = fr.face_encodings(img)
face_embedding里面包含了img中人臉的編碼,如果檢測(cè)到多個(gè)人臉的話會(huì)包含多個(gè)人臉編碼特征。
Dlib 的這個(gè)模型是在LFW數(shù)據(jù)集上訓(xùn)練的,也可以用來(lái)進(jìn)行人臉識(shí)別等,人臉比對(duì)等。
有了特征還需要對(duì)應(yīng)的分類,list_attr_celeba.csv 中包含了celeba數(shù)據(jù)集中的各個(gè)屬性的label,這里我們只使用Male和Smiling兩個(gè)屬性。
一個(gè)可以參考的數(shù)據(jù)準(zhǔn)備腳本:
import os
import timeit
import cv2
from skimage import io as io
import face_recognition as fr
import numpy as np
import pickle
from tqdm import tqdm
from sklearn import datasets, svm, metrics
import pandas as pd
data_path = "/home/ubuntu/ihandy_seg/data/img_align_celeba"
table = pd.read_csv("/home/ubuntu/ihandy_seg/data/list_attr_celeba.csv")
print(table.columns.values)
img_label = table.set_index('image_id').to_dict()["Smiling"]
def main():
count = 0
gender_data = list()
img_files = [f for f in os.listdir(data_path) if not f.startswith('.')]
for img_file in tqdm(img_files[0:5000]):
try:
# print('Processing {}'.format(img_file))
print(os.path.join(data_path, img_file))
img = io.imread(os.path.join(data_path, img_file))
face_embedding = fr.face_encodings(img)
if len(face_embedding) != 1:
print("Failed")
continue
single_data = list()
single_data.append(face_embedding[0])
single_data.append(img_label[img_file])
gender_data.append(single_data)
except Exception as e:
print(e)
continue
print('Saving as a pkl file')
with open('celeba_smiling_data.pkl','wb') as f:
pickle.dump(gender_data, f)
print('Finished')
if __name__ == '__main__':
main()
分類器訓(xùn)練
這里我們使用sklearn 的 SVM作為分類器,使用face embedding也就是提取的128維人臉特征作為分類器的輸入,使用sklearn 的 GridSearch進(jìn)行超參數(shù)搜索, 一共4865張圖片,使用4000張作為訓(xùn)練數(shù)據(jù),865張作為測(cè)試數(shù)據(jù)。
param_grid = {'C': [1e1, 1e2],
'gamma': [10, 100],
'decision_function_shape':["ovo"],
"degree":[3,4]}
classifier = GridSearchCV(svm.SVC(kernel='rbf', class_weight='balanced', verbose=True),
param_grid, cv=5)
classifier.fit(embedding_list_train, gender_label_list_train)
expected = gender_label_list_test
predicted = classifier.predict(embedding_list_test)
print("Classification report for classifier %s:\n%s\n"
% (classifier, metrics.classification_report(expected, predicted)))
print("Confusion matrix:\n%s" % metrics.confusion_matrix(expected, predicted))
分類結(jié)果:
針對(duì)性別分類測(cè)試取得了99%的準(zhǔn)確度,而針對(duì)微笑/不微笑的分類測(cè)試只有68%準(zhǔn)確度。
性別:
precision recall f1-score support
-1 0.98 1.00 0.99 512
1 0.99 0.98 0.99 353
micro avg 0.99 0.99 0.99 865
macro avg 0.99 0.99 0.99 865
weighted avg 0.99 0.99 0.99 865
Confusion matrix:
[[510 2]
[ 8 345]]
1: Male, -1: Female


微笑:
precision recall f1-score support
-1 0.68 0.73 0.70 446
1 0.69 0.63 0.66 419
micro avg 0.68 0.68 0.68 865
macro avg 0.68 0.68 0.68 865
weighted avg 0.68 0.68 0.68 865
Confusion matrix:
[[326 120]
[155 264]]
所有代碼在這里:
https://github.com/ItchyHiker/Face_Attributes_Classification_with_Dlib