人脸分类
#用sklearn中自带的程序来加载数据
from sklearn.datasets import fetch_lfw_people
lfw_people = fetch_lfw_people(min_faces_per_person=70, resize=0.4)
#数据集介绍:图片数大于等于70张人有3个,3个人加起来总图片有760张,每张图片大小50*37(总特征为1850个)
print(lfw_people.data.shape)
print(lfw_people.images.shape)
print(lfw_people.target.shape)
print(lfw_people.target_names.shape)
import matplotlib.pyplot as plt
fig, ax = plt.subplots(3, 4) #plt.subplots函数,直接在函数内部设置子图纸信息,返回值: figure实例fig,AxesSubplot实例ax,fig代表整个图纸
#ax代表坐标轴和画的子图
for i, axi in enumerate(ax.flat):
axi.imshow(lfw_people.images[i], cmap='bone') #将标量数据映射到彩色图,将颜色 #映射为’bone‘
axi.set(xticks=[], yticks=[],xlabel=lfw_people.target_names[lfw_people.target[i]])
#由于每张图50*37,1850个像素点也就是1850个特征,所以得进行降维
from sklearn.svm import SVC
from sklearn.decomposition import PCA
from sklearn.pipeline import make_pipeline
#原始1875D==>150D,whiten白化:使每个特征具有相同的方差
pca = PCA(n_components=150, whiten=True, random_state=42)
#支持向量机用高斯核函数,class_weight每个类所占据的权重
svc = SVC(kernel='rbf', class_weight='balanced')
#使用pca进行数据降维之后再训练一个SVM的工作流程
model = make_pipeline(pca, svc)
#数据集划分
from sklearn.model_selection import train_test_split
Xtrain,Xtest,ytrain,ytest= train_test_split(lfw_people.data, lfw_people.target,random_state=40)
Xtrain.shape,Xtest.shape
from sklearn.model_selection import GridSearchCV #用来模型的参数选择
#目标函数的惩罚系数C,用来平衡分类间隔margin和错分样本的
param_grid = {'svc__C': [1, 5, 10],
'svc__gamma': [0.0001, 0.0005, 0.001]}#核函数的系数
grid = GridSearchCV(model, param_grid)
%time grid.fit(Xtrain, ytrain)
print(grid.best_params_) #描述了已取得最佳结果的参数的组合
model_new = grid.best_estimator_ #使用最佳结果的参数所建立的估计器
yfit = model_new.predict(Xtest)
from sklearn.metrics import classification_report #输出评价指标
print(classification_report(ytest, yfit,target_names=lfw_people.target_names))
#展示部分分类结果
fig, ax = plt.subplots(3,4)
for i, axi in enumerate(ax.flat):
axi.imshow(Xtest[i].reshape(50,37), cmap='bone')
axi.set(xticks=[], yticks=[])
axi.set_ylabel(lfw_people.target_names[yfit[i]].split()[-1],color='black' if yfit[i] == ytest[i] else 'red')
fig.suptitle('Predicted Names; Incorrect Labels in Red', size=14)
#输出混淆矩阵
import seaborn as sns
from sklearn.metrics import confusion_matrix #混淆矩阵
mat = confusion_matrix(ytest, yfit)
sns.heatmap(mat.T, square=True, annot=True, fmt='d', cbar=False,
xticklabels=lfw_people.target_names,
yticklabels=lfw_people.target_names)
plt.xlabel('true label')
plt.ylabel('predicted label');
2.2.2 人脸识别
1.数据处理
# 批量修改图片文件名
import os
import re
import sys
path = 'E:/pycharm/人脸识别项目/opencv/data/'
imagePaths = []
n=0
for f in os.listdir(path) :
path1 =os.path.join(path,f)
currentpath = os.getcwd() # 得到进程当前工作目录 data/
os.chdir(path1) # 将当前工作目录修改为待修改文件夹的位置
for s in os.listdir(path1):
a = re.split(r'_', s)
os.rename(s, (str(n) + '_' + a[-1]))
s=str(n) + '_' + a[-1]
imagePaths.append(os.path.join(path1, s))
n+=1
os.chdir(currentpath) # 改回程序运行前的工作目录
sys.stdin.flush() # 刷新
2.信息录入
import cv2 as cv
import os
import sys
#摄像头
cap = cv.VideoCapture(0)
flag = 1
num = 1
path = 'E:/pycharm/人脸识别项目/opencv/data/'
folderpaths=[]
for f in os.listdir(path):
folderpaths.append(os.path.join(path, f))
folder_number = len(folderpaths)
while(cap.isOpened()):#检测是否为开启状态
ret_flag,Vshow = cap.read()#得到每帧图像
cv.imshow("Capture_test",Vshow)#显示图像
k = cv.waitKey(1) #按键判断
if k == ord('y'):
file_name = input('请输入录入人员姓名')
os.mkdir(r'E:/pycharm/人脸识别项目/opencv/data/'+file_name)
sys.stdin.flush() # 刷新
continue
if k == ord('s'):
cv.imwrite('E:/pycharm/人脸识别项目/opencv/data/{}/'.format(file_name)+str(folder_number)+'_000'+str(num)+".jpg",Vshow)
print("success to save "+str(num)+".jpg")
print('-------------------')
num += 1
elif k == ord(' '):
break
#释放摄像头
cap.release()
#释放内存
cv.destroyAllWindows()
3.训练数据
import cv2 as cv
import os
from PIL import Image
import numpy as np
def getImageAndLabels(path):
#储存人脸数据
facesSamples=[]
#储存姓名数据
ids=[]
#储存图片路径信息
imagePaths=[]
for f in os.listdir(path):
path1 = os.path.join(path, f)
for s in os.listdir(path1):
imagePaths.append(os.path.join(path1, s))
#加载分类器
face_detector=cv.CascadeClassifier('E:/Ancoda/Lib/site-packages/opencv_python-4.6.0.66. dist-info/ opencv/sources/data/haarcascades/haarcascade_frontalface_alt.xml')
#遍历所用的图片
for imagePath in imagePaths:
#打开图片,灰度化PIL有九种不同的模式,1(黑白图),L(灰度 图),P,RGB,RGBA,CMYK,YCbCr,I,F
PIL_img=Image.open(imagePath).convert('L')
#将图片转换为数组
img_numpy=np.array(PIL_img,'uint8')
#获取人脸特征
faces = face_detector.detectMultiScale(img_numpy)
#获取每张图片的id和照片
id = int(os.path.split(imagePath)[1].split('.')[0].split('_')[0])
#
for x,y,w,h in faces:
ids.append(id)
facesSamples.append(img_numpy[y:y+h,x:x+w])
print('id:',id)
print('fs:',facesSamples)
return facesSamples,ids
if __name__=='__main__':
path='E:/pycharm/人脸识别项目/opencv/data/'
#获取图像数组和id标签数组和姓名
faces,ids=getImageAndLabels(path)
#加载识别器
recognizer = cv.face.LBPHFaceRecognizer_create()
#训练
recognizer.train(faces,np.array(ids))
#保存文件
recognizer.write('train_data.yml')
4.人脸识别
import cv2 as cv
import os
#加载训练数据集和文件
recognizer=cv.face.LBPHFaceRecognizer_create()
recognizer.read('train_data.yml')
names=[]#创建名字列表,id唯一对应名字
path='E:/pycharm/人脸识别项目/opencv/data/'
for f in os.listdir(path):#填充名字列表
names.append(f)
# 准备识别图片
def face_detect_demo(img):
gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
# opencv 里面的分类器
face_detector=cv.CascadeClassifier('E:/Ancoda/Lib/site-packages/opencv_python-4.6.0.6 6.dist-info/opencv/sources/data/haarcascades/haarcascade_frontalface_alt2.xml')
face = face_detector.detectMultiScale(gray)
for x, y, w, h in face:
cv.rectangle(img, (x, y), (x + w, y + h), color=(0, 0, 225), thickness=2)
# 人脸识别
ids, confidence = recognizer.predict(gray[y:y + h, x:x + w])
print('标签id:', names[ids], '置信评分:', confidence)
if confidence < 80: cv.putText(img,str(names[ids]),(x+10,y-10),cv.FONT_HERSHEY_SIMPLEX,0.75,(0,255,0),1)
else:
cv.putText(img,'unknow',(x+10,y-10),cv.FONT_HERSHEY_SIMPLEX,0.75,(0,225,0),1)
cv.imshow('result', img)
cv.waitKey(0)
cv.destroyAllWindows()
if __name__=='__main__':
img = cv.imread('Alex_Barros_0001.jpg')
face_detect_demo(img)