import cv2
import matplotlib.pyplot as plt
import os
import numpy as np
# 简单测试
# img = cv2.imread('face.jpg')
# #采用级联分类器
# detector = cv2.CascadeClassifier('haarcascade_frontalface_alt.xml')
# #进行人脸检测
# rects = detector.detectMultiScale(img,scaleFactor = 1.1,minNeighbors = 3,minSize = (20,20),flags =cv2.CASCADE_SCALE_IMAGE)
# #返回的就是人脸的位置
# # print(rects)
# for x,y,w,h in rects:
# #截取人脸,并且都转化为200*200的固定大小
# cv2.rectangle(img, (x,y),(x+w,y+h), (0,255,0), (2))
# img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
# plt.imshow(img)
# plt.axis('off')
# plt.show()
#实战
def face_detect(face_path ,predict_face_path):
#如果文件夹不存在则创建文件夹
if not os.path.exists(predict_face_path):
os.mkdir(predict_face_path)
#循环face_path下面的每个文件夹
for dirs in os.listdir(face_path):
#检测是不是文件夹,因为图片文件都是放在单独的文件夹中
if os.path.isdir(os.path.join(face_path ,dirs)):
#说明已经得到了人脸照片所在的文件夹,为了方便查看,直接把原来的文件夹名称搬过去
predict_face_sub_path = os.path.join(predict_face_path ,dirs)
# print(predict_face_sub_path)
if not os.path.exists(predict_face_sub_path):
os.mkdir(predict_face_sub_path)
#获取各个明星人脸图片所在的文件夹
files = os.path.join(face_path ,dirs)
# print(files)
for file in os.listdir(files):
#获取人脸图片的绝对路径
file = os.path.join(files ,file)
print(file)
loc_face(file ,predict_face_sub_path)
def loc_face(file ,predict_face_sub_path):
#获取文件名
name = os.path.basename(file)
#加载图像
image = cv2.imread(file)
#为了方便识别,习惯变成灰度图
image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
#采用级联分类器
detector = cv2.CascadeClassifier('haarcascade_frontalface_alt.xml')
#进行人脸检测,返回的就是人脸的位置
rects = detector.detectMultiScale(image ,scaleFactor = 1.1,
minNeighbors = 3 ,minSize = (20 ,20),
flags =cv2.CASCADE_SCALE_IMAGE)
#这里不直接绘制正方形,直接把识别后的图片给保存下来
print(image)
for (x ,y ,w ,h) in rects:
#统一裁剪成为200x200的大小,注意这里的切片的顺序不能错了
f = cv2.resize(image[y: y +h ,x: x +w], (200 ,200))
#然后保存,注意这里的
cv2.imwrite(os.path.join(predict_face_sub_path ,name) ,f)
#测试一下为什么要进行image[y:y+h,x:x+w]
# import numpy as np
# data = np.array(
# [[216, 216, 215, 212, 212, 212],
# [216 ,216 ,215 ,211 ,211 ,211],
# [216 ,216 ,215 , 210, 210, 210],
# [ 86 , 85 , 82 , 137, 139, 141],
# [ 85 , 83 , 81 , 139, 140, 141],
# [ 84 , 83 , 80 , 140, 141, 142]])
# x,y,w,h = 1,2,3,4
# print(data[x:x+w,y:y+h])
# print(data[y:y+h,x:x+w])
#制作标签
def get_label(predict_face_path):
#生成一个label.txt文件保存图片路径和标签
f = open('label.txt', 'w')
#表示人脸的标签,默认是从0开始
label = 0
for dirpath ,dirnames ,files in os.walk(predict_face_path):
#获取所有的子文件夹
for sub_dir in dirnames:
#完整的子文件夹路径
sub_dir_path = os.path.join(dirpath ,sub_dir)
#这时候就可以循环遍历每一个子文件夹,提取图片数据了
for file in os.listdir(sub_dir_path):
#注意提取的图片名称是相对路径,需要补充完整
file_path = os.path.join(sub_dir_path ,file)
#获得完整路径后就可以判断是不是图片
if file_path.split('.')[-1] in ['png' ,'jpg' ,'jpeg']:
f.write(file_path)
#为了之后方便提取标签,加一个分割符号
f.write(";")
#再写入标签进行换行
f.write(str(label))
f.write("\n")
#每个子文件夹遍历完毕后,就进行累加,完成标签制作
label += 1
#关闭文件
f.close()
#训练模型
#创建两个列表保存图片数据和标签
def train_model():
images = []
labels = []
f = open('label.txt' ,'r')
for line in f:
#之前保留的分割符就派上用场了
img_path = line.split(';')[0]
# print(img_path)
label = line.split(';')[-1]
#再将图片和标签分别存放在两个列表中
img = cv2.imread(img_path ,0) #问题就出在这个0上面,imread按单通道的方式读入图像,即灰度图像
images.append(img)
#注意最后的标签是要转化为数值
labels.append(int(label))
print(images)
#这里需要安装opencv扩展包pip install opencv-contrib-python
model = cv2.face.EigenFaceRecognizer_create()
#训练模型
model.train(np.array(images) ,np.array(labels))
#保存模型
model.save('my_face_detect_model.xml')
#人脸识别
#定义要显示的人脸的名字
def face_test():
name = ['AB' ,'xiaoming' ,'xiaoxiannv']
#定义人脸的识别模型
model = cv2.face.EigenFaceRecognizer_create()
#载入训练好的模型
model.read('my_face_detect_model.xml')
#读入测试集进行验证
for file in os.listdir('test'):
#文件的完整路径
file_path = os.path.join('test', file)
#还是判断文件类型
if file_path.split('.')[-1] in ['png' ,'jpg' ,'jpeg']:
img = cv2.imread(file_path)
#为了方便识别,尽量变成灰度图
img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
#级联分类器
detector = cv2.CascadeClassifier('haarcascade_frontalface_alt.xml')
rects = detector.detectMultiScale(img_gray ,scaleFactor = 1.1,
minNeighbors = 3 ,minSize = (20 ,20),
flags =cv2.CASCADE_SCALE_IMAGE)
#循环每一张人脸
for (x ,y ,w ,h) in rects:
#画矩形框
cv2.rectangle(img ,(x ,y) ,( x +w , y +h) ,(0 ,255 ,0) ,2)
#人脸识别
face = cv2.resize(img_gray[y: y +h ,x: x +w] ,(200 ,200))
#预测人物
params = model.predict(face)
print(params)
#写上人物的名字
cv2.putText(img ,name[params[0]] ,(x , y -20) ,cv2.FONT_HERSHEY_SIMPLEX ,1 ,(255 ,0 ,0) ,2)
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
plt.imshow(img)
plt.axis('off')
plt.show()
if __name__ == "__main__":
face_test()
# train_model()
# face_detect('train','predict_faces')
# get_label('predict_faces')
检查问题
最新发布