一、训练思路
1、opencv读取数据集 2、dlib人脸检测器定位人脸 3、获取每张图片的HOG特征向量组 4、利用SVM进行训练 5、得出模型并保存
1、读取模型,读取照片或者打开摄像头进行实时检测 2、将每一帧或者图片的HOG特征值提取出来并预测 3、得出结果并显示出来
二、代码
import numpy as np
import cv2
import dlib
import random
from sklearn.svm import SVC
from sklearn.svm import LinearSVC
from sklearn.pipeline import Pipeline
import os
import joblib
from sklearn.preprocessing import StandardScaler,PolynomialFeatures
import tqdm
folder_path='F:/jupyter/source/picture/genki4k/'
label='labels.txt'
pic_folder='files/'
- 获得默认的人脸检测器和训练好的人脸68特征点检测器
def get_detector_and_predicyor():
detector = dlib.get_frontal_face_detector()
"""
功能:人脸检测画框
参数:PythonFunction和in Classes
in classes表示采样次数,次数越多获取的人脸的次数越多,但更容易框错
返回值是矩形的坐标,每个矩形为一个人脸(默认的人脸检测器)
"""
predictor = dlib.shape_predictor('shape_predictor_68_face_landmarks.dat')
return detector,predictor
detector,predictor=get_detector_and_predicyor()
def cut_face(img,detector,predictor):
img_gry=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
rects = detector(img_gry, 0)
if len(rects)!=0:
mouth_x=0
mouth_y=0
landmarks = np.matrix([[p.x, p.y] for p in predictor(img,rects[0]).parts()])
for i in range(47,67):
mouth_x+=landmarks[i][0,0]
mouth_y+=landmarks[i][0,1]
mouth_x=int(mouth_x/20)
mouth_y=int(mouth_y/20)
img_cut=img_gry[mouth_y-20:mouth_y+20,mouth_x-20:mouth_x+20]
return img_cut
else:
return 0
def get_feature(files_train,face,face_feature):
for i in tqdm.tqdm(range(len(files_train))):
img=cv2.imread(folder_path+pic_folder+files_train[i])
cut_img=cut_face(img,detector,predictor)
if type(cut_img)!=int:
face.append(True)
cut_img=cv2.resize(cut_img,(64,64))
padding=(8,8)
winstride=(16,16)
hogdescrip=hog.compute(cut_img,winstride,padding).reshape((-1,))
face_feature.append(hogdescrip)
else:
face.append(False)
face_feature.append(0)
def filtrate_face(face,face_feature,face_site):
face_features=[]
label_flag=[]
with open(folder_path+label,'r') as f:
lines=f.read().splitlines()
for i in tqdm.tqdm(range(len(face_site))):
if face[i]:
face_features.append(face_feature.pop(0))
label_flag.append(int(lines[face_site[i]][0]))
else:
face_feature.pop(0)
datax=np.float64(face_features)
datay=np.array(label_flag)
return datax,datay
def PolynomialSVC(degree,c=10):
return Pipeline([
("poly_features", PolynomialFeatures(degree=degree)),
("scaler", StandardScaler()),
("svm_clf", LinearSVC(C=10, loss="hinge", random_state=42,max_iter=10000))
])
def train(files_train,train_site):
'''
files_train:训练文件名的集合
train_site :训练文件在文件夹里的位置
'''
train_face=[]
train_feature=[]
get_feature(files_train,train_face,train_feature)
train_x,train_y=filtrate_face(train_face,train_feature,train_site)
svc=PolynomialSVC(degree=1)
svc.fit(train_x,train_y)
return svc
def test(files_test,test_site,svc):
'''
files_train:训练文件名的集合
train_site :训练文件在文件夹里的位置
'''
test_face=[]
test_feature=[]
get_feature(files_test,test_face,test_feature)
test_x,test_y=filtrate_face(test_face,test_feature,test_site)
pre_y=svc.predict(test_x)
ac_rate=0
for i in range(len(pre_y)):
if(pre_y[i]==test_y[i]):
ac_rate+=1
ac=ac_rate/len(pre_y)*100
print("准确率为"+str(ac)+"%")
return ac
winsize=(64,64)
blocksize=(32,32)
blockstride=(16,16)
cellsize=(8,8)
nbin=9
hog=cv2.HOGDescriptor(winsize,blocksize,blockstride,cellsize,nbin)
files=os.listdir(folder_path+pic_folder)
- 使用10-fold cross validation
ac=float(0)
for j in range(10):
site=[i for i in range(4000)]
train_site=random.sample(site,3600)
test_site=[]
for i in range(len(site)):
if site[i] not in train_site:
test_site.append(site[i])
files_train=[]
for i in range(len(train_site)):
files_train.append(files[train_site[i]])
files_test=[]
for i in range(len(test_site)):
files_test.append(files[test_site[i]])
svc=train(files_train,train_site)
ac=ac+test(files_test,test_site,svc)
save_path='F:/jupyter/source/model/smile'+str(j)+'(hog).pkl'
joblib.dump(svc,save_path)
ac=ac/10
print("平均准确率为"+str(ac)+"%")
def test1(files_test,test_site,svc):
'''
files_train:训练文件名的集合
train_site :训练文件在文件夹里的位置
'''
test_face=[]
test_feature=[]
get_feature(files_test,test_face,test_feature)
test_x,test_y=filtrate_face(test_face,test_feature,test_site)
pre_y=svc.predict(test_x)
tp=0
tn=0
for i in range(len(pre_y)):
if pre_y[i]==test_y[i] and pre_y[i]==1:
tp+=1
elif pre_y[i]==test_y[i] and pre_y[i]==0:
tn+=1
f1=2*tp/(tp+len(pre_y)-tn)
print(f1)
svc7=joblib.load('F:/jupyter/source/model/smile9(hog).pkl')
site=[i for i in range(4000)]
train_site=random.sample(site,3600)
test_site=[]
for i in range(len(site)):
if site[i] not in train_site:
test_site.append(site[i])
files_test=[]
for i in range(len(test_site)):
files_test.append(files[test_site[i]])
test1(files_test,test_site,svc7)
def smile_detector(img,svc):
cut_img=cut_face(img,detector,predictor)
a=[]
if type(cut_img)!=int:
cut_img=cv2.resize(cut_img,(64,64))
padding=(8,8)
winstride=(16,16)
hogdescrip=hog.compute(cut_img,winstride,padding).reshape((-1,))
a.append(hogdescrip)
result=svc.predict(a)
a=np.array(a)
return result[0]
else :
return 2
pic_path='F:/jupyter/source/picture/test.jpg'
img=cv2.imread(pic_path)
result=smile_detector(img,svc7)
if result==1:
img=cv2.putText(img,'smile',(21,50),cv2.FONT_HERSHEY_COMPLEX,2.0,(0,255,0),1)
elif result==0:
img=cv2.putText(img,'no smile',(21,50),cv2.FONT_HERSHEY_COMPLEX,2.0,(0,255,0),1)
else:
img=cv2.putText(img,'no face',(21,50),cv2.FONT_HERSHEY_COMPLEX,2.0,(0,255,0),1)
cv2.imshow('video', img)
cv2.waitKey(0)
camera = cv2.VideoCapture(0)
ok=True
flag=0
while ok:
ok,img = camera.read()
result=smile_detector(img,svc7)
if result==1:
img=cv2.putText(img,'smile',(21,50),cv2.FONT_HERSHEY_COMPLEX,2.0,(0,255,0),1)
elif result==0:
img=cv2.putText(img,'no smile',(21,50),cv2.FONT_HERSHEY_COMPLEX,2.0,(0,255,0),1)
else:
img=cv2.putText(img,'no face',(21,50),cv2.FONT_HERSHEY_COMPLEX,2.0,(0,255,0),1)
cv2.imshow('video', img)
k = cv2.waitKey(1)
if k == 27:
break
elif k==115:
pic_save_path='F:/jupyter/source/picture/result/'+str(flag)+'.jpg'
flag+=1
cv2.imwrite(pic_save_path,img)
camera.release()
cv2.destroyAllWindows()
- 检测效果
三、总结
整个过程是在前面实验的基础上完成的,相当于是一个综合应用。
四、参考资料
微笑识别(HOG+SVM+opencv+python)
|