小标
2018-09-29
来源 :
阅读 2011
评论 0
摘要:本文主要向大家介绍了机器学习入门之Python 3 利用 Dlib 19.7 和 sklearn机器学习模型 实现人脸微笑检测,通过具体的内容向大家展现,希望对大家学习机器学习入门有所帮助。
本文主要向大家介绍了机器学习入门之Python 3 利用 Dlib 19.7 和 sklearn机器学习模型 实现人脸微笑检测,通过具体的内容向大家展现,希望对大家学习机器学习入门有所帮助。
利用机器学习的方法训练微笑检测模型,输入一张人脸照片,判断是否微笑;
识别精度在95%附近(使用的数据集中69张没笑脸,65张有笑脸);
效果:
图1 测试图像与检测结果
工程利用python 3 开发,借助Dlib进行 人脸嘴部20个特征点坐标(40维特征)的提取;
然后根据这 40维输入特征 作为模型输入, 1维特征(1代表有微笑 / 0代表没微笑)作为输出,进行ML建模;
利用几种机器学习模型进行建模,达到一个二分类(分类有/无笑脸)的目的,然后分析模型识别精度和性能,并且可以识别给定图片的人脸是否微笑;
py文件:
1. Get_features.py :
returnfeatures(): 输入人脸图像路径,利用dlib的“shape_predictor_68_face_landmarks.dat”提取嘴部20个特征点坐标的40个特征值;
writeintoCSV(): 将40维特征输入和1维的输出标记(1代表有微笑/0代表没微笑)写入CSV文件中;
2. ML_ways.py:
pre_data(): 读取CSV中的数据,然后提取出训练集和测试集;
way_LR(): Logistic Regressio, 罗吉斯特回归方法建模;
way_SGD(): Stochastic Gradient Decent, 随机梯度下降法建模;
way_SVM(): Supported Vector Machine, 支持向量机法建模;
way_MLP(): Multi-Layer Perceptron, 多层神经网络法建模;
3. test_single_pic.py:
输入给定测试图像,用ML模型检测其有/无笑脸;
(实现稍微比较复杂,感兴趣的可以结合之前博客看看:
Python 3 利用 Dlib 19.7 进行人脸识别:
//www.cnblogs.com/AdaminXie/p/7905888.html
Python 3 利用 Dlib 19.7 进行人脸68个特征点的标定:
//www.cnblogs.com/AdaminXie/p/8137580.html
Python 3 利用机器学习模型进行手写体识别:
//www.cnblogs.com/AdaminXie/p/8249858.html)
1.开发环境
python: 3.6.3
dlib: 19.7
OpenCv, numpy, sklearn, pandas, os, csv等
Get_features.py中调用的库:
1 import dlib # 人脸识别的库dlib
2 import numpy as np # 数据处理的库numpy
3 import cv2 # 图像处理的库OpenCv
4 import os # 读取文件
5 import csv # csv操作
ML_ways.py中调用的库:
1 # pd读取CSV
2 import pandas as pd
3
4 # 分割数据
5 from sklearn.model_selection import train_test_split
6
7 # 用于数据预加工标准化
8 from sklearn.preprocessing import StandardScaler
9
10 # 使用的四种ML模型
11 from sklearn.linear_model import LogisticRegression
12 from sklearn.linear_model import SGDClassifier
13 from sklearn.svm import LinearSVC
14 from sklearn.neural_network import MLPClassifier
使用的人脸来自于 The MUCT Face Database(Link: //www.milbo.org/muct/),在此十分感谢!
(The MUCT database was prepared by Stephen Milborrow, John Morkel, and Fred Nicolls in December 2008 at the University Of Cape Town. We would like to send out a thanks to the people who allowed their faces to be used.)
2.设计流程
工作内容主要以下两大块:提取人脸特征 和 ML建模;
整体的设计流程如下图所示:
图2 总体设计流程图
2.1 提取人脸特征:
该部分的设计流程图:
图3 人脸提取特征部分流程图
我先在项目目录下建立两个文件夹,分别存放有笑脸的人脸,和无笑脸的人脸,这样之后读取的时候就可以知道人脸的标记有/无人脸;
关于利用dlib进行人脸68个特征点的提取,在我之前另一篇博客里面介绍过:
(link: //www.cnblogs.com/AdaminXie/p/7905888.html);
本项目中只使用其中嘴部20个特征点的坐标作为特征输入,20个点的序号如下图所示:
图4 dlib标定的嘴部特征点序号
20个特征点40个坐标值,和输出标记的获取,由returnfeatures函数实现;
输入图像文件所在路径,返回的的是数组features_csv(前40个为特征点坐标值,第41个为标记(1代表有笑脸,0代表无笑脸))
1 # ML_smiles
2 # 2018-1-27
3 # By TimeStamp
4 # cnblogs: //www.cnblogs.com/AdaminXie/
5
6
7 detector = dlib.get_frontal_face_detector()
8 predictor = dlib.shape_predictor(‘shape_predictor_68_face_landmarks.dat‘)
9
10 # 输入图像文件所在路径,返回一个41维数组(包含提取到的40维特征和1维输出标记)
11 def returnfeatures(path_pic, XXXpic, features_csv):
12
13 # 输入: path_pic: 图像文件所在目录
14 # XXXpic: 图像文件名
15
16 # 输出: features_csv 41维度的数组,前40维为(提取的20个特征点坐标的40个值),第41维为标记output
17
18 # 比如 path_pic + XXXpic = "F:/code/test.jpg" 精确到jpg
19 img = cv2.imread(path_pic + XXXpic)
20 # 取灰度
21 img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
22
23 # 计算68点坐标
24 pos_68 = []
25 rects = detector(img_gray, 0)
26 landmarks = np.matrix([[p.x, p.y] for p in predictor(img, rects[0]).parts()])
27 for idx, point in enumerate(landmarks):
28 # 68点的坐标
29 pos = (point[0, 0], point[0, 1])
30 pos_68.append(pos)
31
32 # 将点49-68写入csv
33 # 即pos_68[48]-pos_68[67]
34 for i in range(48, 68):
35 features_csv.append(pos_68[i][0])
36 features_csv.append(pos_68[i][1])
37
38 #print(features_csv)
39 return features_csv
然后就遍历两个存放有/无笑脸的文件夹,读取图像文件,然后利用returnfeatures()函数得到特征值,写入CSV中:
1 # ML_smiles
2 # 2018-1-27
3 # By TimeStamp
4 # cnblogs: //www.cnblogs.com/AdaminXie/
5 # Get_features.py
6
7
8 # 读取图像所在的路径
9 path_pic_smile = "F:/code/python/P_ML_smile/pic/database/smile/"
10 path_pic_nosmile = "F:/code/python/P_ML_smile/pic/database/no/"
11
12 # 获取路径下的图像文件
13 namedir_smile = os.listdir(path_pic_smile)
14 namedir_nosmile = os.listdir(path_pic_nosmile)
15
16 # 存储提取特征数据的CSV的路径
17 path_csv = "F:/code/python/P_ML_smile/data_csv/"
18
19 def writeintoCSV():
20 with open(path_csv+"data.csv", "w", newline="") as csvfile:
21 writer = csv.writer(csvfile)
22
23 # 处理带笑脸的图像
24 print("######## with smiles #########")
25 for i in range(len(namedir_smile)):
26 print("pic:", path_pic_smile, namedir_smile[i])
27
28 # 用来存放41维特征
29 features_csv_smiles = []
30
31 # 利用 returnfeatures 函数提取特征
32 returnfeatures(path_pic_smile, namedir_smile[i], features_csv_smiles)
33 features_csv_smiles.append(1)
34 print("features:", features_csv_smiles, "\n")
35
36 # 写入CSV
37 writer.writerow(features_csv_smiles)
38
39 # 处理不带笑脸的图像
40 print("######## no smiles #########")
41 for i in range(len(namedir_nosmile)):
42 print("pic:", path_pic_nosmile, namedir_nosmile[i])
43
44 # 用来存放41维特征
45 features_csv_nosmiles = []
46
47 # 利用 returnfeatures 函数提取特征
48 returnfeatures(path_pic_nosmile, namedir_nosmile[i], features_csv_nosmiles)
49 features_csv_nosmiles.append(0)
50 print("features:", features_csv_nosmiles, "\n")
51
52 # 写入CSV
53 writer.writerow(features_csv_nosmiles)
会得到一个41列的CSV文件,前40列为40维的输入特征,第41列为笑脸标记。
2.2 ML建模和测试
这部分机器学习模型使用比较简单,之前的特征提取已经完成,写入了CSV文件中;
接下来就是要从CSV中将想要的数据集提取出来,利用sklearn进行机器学习建模。
2.2.1 数据预加工
利用pands.read_csv读取CSV文件,然后利用train_test_split进行数据分割;
得到 训练集:X_train, y_train 和 测试集:X_test, y_test
1 # ML_smiles
2 # 2018-1-27
3 # By TimeStamp
4 # cnblogs: //www.cnblogs.com/AdaminXie/
5 # pre_data() in ML_ways.py
6
7
8 # 从CSV读取数据
9 def pre_data():
10
11 # 41维表头
12 column_names = []
13 for i in range(0, 40):
14 column_names.append("feature_" + str(i+1))
15 column_names.append("output")
16
17 path_csv = "F:/code/python/P_ML_smile/data_csv/"
18
19 rd_csv = pd.read_csv(path_csv+"data.csv", names=column_names)
20
21 # 输出CSV文件的维度
22 print("shape:", rd_csv.shape)
23
24 global X_train, X_test, y_train, y_test
25 X_train, X_test, y_train, y_test = train_test_split(
26 rd_csv[column_names[0:40]],
27 rd_csv[column_names[40]],
28 test_size=0.25,
29 random_state=33)
2.2.2 机器学习建模
几种建模方法在sklearn中实现的代码类似,所以在此只介绍LR,Logisitic Regression罗吉斯特回归方法;
返回ss_LR和LR,需要这两个返回值,是因为之后要利用它们对给定图像的进行检测,之后2.2.3节会介绍;
1 # ML_smiles
2 # 2018-1-27
3 # By TimeStamp
4 # cnblogs: //www.cnblogs.com/AdaminXie/
5 # way_LR() in ML_ways.py
6
7 # 罗吉斯特回归LR
8 def way_LR():
9
10 X_train_LR = X_train
11 y_train_LR = y_train
12
13 X_test_LR = X_test
14 y_test_LR = y_test
15
16 # 标准化数据预加工
17 ss_LR = StandardScaler()
18
19 X_train_LR = ss_LR.fit_transform(X_train_LR)
20 X_test_LR = ss_LR.transform(X_test_LR)
21
22 # 初始化LogisticRegression
23 LR = LogisticRegression()
24
25 # 调用LogisticRegression中的fit()来训练模型参数
26 LR.fit(X_train_LR, y_train_LR)
27
28 # 使用训练好的模型lr对X_test进行预测,结果储存在lr_y_predict中
29 global y_predict_LR
30 y_predict_LR = LR.predict(X_test_LR)
31
32 global lr_score
33 lr_score=LR.score(X_test_LR, y_test_LR)
34 print("The accurary of LR:", LR.score(X_test_LR, y_test_LR))
35
36 return ss_LR, LR
我的数据集里面是69张没笑脸,65张有笑脸,测试精度如下,精度在95%附近:
The accurary of LR: 0.941176470588
The accurary of SGD: 0.882352941176
The accurary of SVM: 0.941176470588
The accurary of MLP: 0.970588235294
2.2.3 测试单张图片
现在我们已经建好机器学习模型,在2.2.2中可以利用sklearn机器学习模型的score函数得到模型精度,但是如果想检测给定图像的笑脸,需要进行该部分工作:
path_test_pic+XXXpic就是需要进行检测的文件路径,需要精确到图像文件,比如“F:/pic/test.pic”;
然后调用Get.features.py中的returnfeatures()函数进行特征提取,得到给定图像的40维特征数组single_features;
如果想利用LR模型测试,接受way_LR()的返回值ss_LR和LR,利用ss_LR对single_features进行标准化处理,然后调用LR.predict进行预测;
然后生成图像窗口,将几种模型的结果显示在图像上。
1 # ML_smiles
2 # 2018-1-27
3 # By TimeStamp
4 # cnblogs: //www.cnblogs.com/AdaminXie/
5 # test_single_pic.py
6
7 import cv2
8
9 from ML_ways import pre_data
10 from ML_ways import way_LR
11 from ML_ways import way_MLP
12 from ML_ways import way_SGD
13 from ML_ways import way_SVM
14
15 # 获得单张人脸的特征点
16 path_test_pic = "F:/code/python/P_ML_smile/pic/"
17 #path_test_pic = "F:/code/pic/faces/the_muct_face_database/jpg/"
18
19 XXXpic = "test1.jpg"
20
21 # 训练LR模型
22 pre_data()
23
24 # 使用标准化参数和ML模型
25 ss_LR, LR = way_LR()
26 ss_SGD, SGD = way_SGD()
27 ss_SVM, SVM = way_SVM()
28 ss_MLP, MLP = way_MLP()
29
30 # 提取单张40维度特征
31 from Get_features import returnfeatures
32 single_features = []
33 returnfeatures(path_test_pic, XXXpic, single_features)
34 #print("single_40_features: ", single_features)
35
36 ############## LR模型预测 ##############
37
38 # 特征数据预加工
39 X_single_LR = ss_LR.transform([single_features])
40 # 利用训练好的LR模型预测
41 y_predict_LR_single = LR.predict(X_single_LR)
42
43 con_LR = str(y_predict_LR_single[0]).replace("1", "smiles").replace("0", "no_smiles")
44 print("LR:", con_LR)
45
46 ############## SGD模型预测 ##############
47
48 # 特征数据预加工
49 X_single_SGD = ss_SGD.transform([single_features])
50 # 利用训练好的SGD模型预测
51 y_predict_SGD_single = SGD.predict(X_single_SGD)
52
53 con_SGD = str(y_predict_SGD_single[0]).replace("1", "smiles").replace("0", "no_smiles")
54 print("SGD:", con_SGD)
55
56 ############## SVM模型预测 ##############
57
58 # 特征数据预加工
59 X_single_SVM = ss_SVM.transform([single_features])
60 # 利用训练好的SVM模型预测
61 y_predict_SVM_single = SVM.predict(X_single_SVM)
62
63 con_SVM = str(y_predict_SVM_single[0]).replace("1", "smiles").replace("0", "no_smiles")
64 print("SVM:", con_SVM)
65
66 ############## MLP模型预测 ##############
67
68 # 特征数据预加工
69 X_single_MLP = ss_MLP.transform([single_features])
70 # 利用训练好的MLP模型预测
71 y_predict_MLP_single = MLP.predict(X_single_MLP)
72
73 con_MLP = str(y_predict_MLP_single[0]).replace("1", "smiles").replace("0", "no_smiles")
74 print("MLP:", con_MLP)
75
76 img = cv2.imread(path_test_pic+XXXpic)
77
78 font = cv2.FONT_HERSHEY_SIMPLEX
79
80 cv2.putText(img, "LR: "+con_LR, (20, 50), font, 1, (0, 0, 255), 1, cv2.LINE_AA)
81 cv2.putText(img, "SGD: "+con_SGD, (20, 100), font, 1, (0, 0, 255), 1, cv2.LINE_AA)
82 cv2.putText(img, "SVM: "+con_SVM, (20, 150), font, 1, (0, 0, 255), 1, cv2.LINE_AA)
83 cv2.putText(img, "MLP: "+con_MLP, (20, 200), font, 1, (0, 0, 255), 1, cv2.LINE_AA)
84
85 cv2.namedWindow("img")#, 2)
86 cv2.imshow("img", img)
87 cv2.waitKey(0)
3.效果
图5 同一个人不同表情的笑脸检测结果
4.总结
自己最近经常使用dlib做人脸识别这块,又在学习机器学习,两者结合尝试做到笑容检测这块;
数据集中有无笑脸是自己进行分类的,而且有写的表情不太好界定,所以选取的是一些笑容比较明显的照片作为有笑脸,所以可能出来模型在检测一些微笑上有误差;
笑容检测模型的数据集测试精度在95%左右,比较理想;
其实人脸笑容检测的话,光靠嘴部特征去判断不太合适,要结合整张人脸特征点进行训练,改进的话也比较简单;
本文由职坐标整理并发布,希望对同学们有所帮助。了解更多详情请关注职坐标人工智能机器学习频道!
喜欢 | 1
不喜欢 | 0
您输入的评论内容中包含违禁敏感词
我知道了

请输入正确的手机号码
请输入正确的验证码
您今天的短信下发次数太多了,明天再试试吧!
我们会在第一时间安排职业规划师联系您!
您也可以联系我们的职业规划师咨询:
版权所有 职坐标-一站式AI+学习就业服务平台 沪ICP备13042190号-4
上海海同信息科技有限公司 Copyright ©2015 www.zhizuobiao.com,All Rights Reserved.
沪公网安备 31011502005948号