书接上文,我们已经选择好了分类器
我们想要对视频进行人脸识别那么,我们需要进行如下操作:
1.导入视频 2.数据训练(将人脸和id对应上) 3.人脸识别(识别视频中的人物并显示id)
目录
一、导入视频
我们最终想要实现的效果是,在视频播放的时候,能够识别人物头像,并标注人物名称,那么第一步便是导入这个视频,其中face_identify就是我们后面需要实现的功能函数,这里我们仅使用上篇所达成的效果进行测试,只能锁定人物头像,效果图如下:
video = cv2.VideoCapture(r"C:\Users\yuehen\Desktop\mp4C.mp4")
#video = cv2.VideoCapture(0)#捕获摄像头
#video = cv2.VideoCapture(r'')#捕获视频
def video_catch(video):
while True:#一个无线循环,不断的寻找帧
flag,frame = video.read()#flag是bool值返回是否有帧,frame是图像文件这一帧的图像
#读取不到帧时跳出
if not flag:
break
face_identify(frame,names)#人脸捕捉函数
if cv2.waitKey(10) & 0xFF == 27:#延迟10毫秒,在期间按下回车则退出
break
video_catch(video)
二、数据训练
2.1 人脸录入
简单的说就是调用摄像头,当你按下s键的时候会截屏并将截取的图像作为人脸保存到固定位置
def face_load(name):
cap = cv2.VideoCapture(0)#调取摄像头
falg = 1
while (cap.isOpened()):#当摄像头打开时
ret_falg,video_image = cap.read()
key = cv2.waitKey(1)&0xFF#按键等待
if key == ord('s'):#如果按下s键
cv2.imwrite(r"C:\Users\yuehen\Desktop\face" + str(name) +".jpg",video_image)
print("success to save" + str(name) + ".jpg")
elif key == ('c'):#按下c键退出
break
name = input("请输入要录入的人物名称")
face_load(name)
2.2 数据导入
将指定文件夹下的人脸图像作为训练集进行模型训练
通过命名规则来确定标签,譬如:1.胡歌25.jpg,此处的1就是我们要获取的标签。
def getImageID(path):
faceSamples = []#用于存储人脸数据
ids = [] #存储对应id
#os.listdir(path)用于返回指定目录中的所有文件和文件夹的列表
#os.path.join(path, f)用于将目录路径和文件名结合起来形成完整的文件路径
#最后也就获得了一个列表里面存储了目录下的所有文件的地址以及文件名称
imagePaths = [os.path.join(path,f) for f in os.listdir(path)]
face_detect = cv2.CascadeClassifier(r"E:\python\Lib\site-packages\cv2\data\haarcascade_frontalface_alt2.xml")
for imagePath in imagePaths:
#Image.open().convert()函数有9种不同的打开方式
# 1:黑白图 L:灰度图(舍弃小数部分) F:灰度图(浮点) I:灰度图(整形)
# P:彩色图 RGB:RGB格式的彩色图 YCbCr:(彩色图像) CMYK:全彩印刷 RGBA:彩色图像透明
PIL_img = Image.open(imagePath).convert('L')
img_np = np.array(PIL_img,'uint8')#以数组的形式存储对象
faces = face_detect.detectMultiScale(img_np)
# os.path.split(imagePath)[1]取出文件名split('.')[0]取出'.'之前str,也就是标签
id = str (os.path.split(imagePath)[1].split('.')[0])
for x,y,w,h in faces:
ids.append(id)
faceSamples.append(img_np[y:y+h,x:x+w])
return faceSamples,ids
path = r"C:\Users\yuehen\Desktop\face"
getImageID(path)
我们尝试打印faceSamples 以及ids,如下图:(注意,此处的faceSamples与ids返回的是一个list对象)
2.3输出训练后的yml文件
1.传入文件路径
2.我们要对两个返回值进行格式处理
3.创建一个训练的实例对象
4.利用train函数训练对象并用save函数保存训练文件
if __name__ =='__main__':
path = r"C:\Users\yuehen\Desktop\face"#训练集路径
#------返回值类型转换------
features = []
labels = []
features,labels = getImageID(path)
#getimageid返回的是两个list数组,需要进行array转换
features = np.array(features,dtype='object')
labels = np.array(labels,dtype='int32')
#创建一个训练的实例对象
face_recognizer = cv2.face.LBPHFaceRecognizer_create()
#训练对象,传入features--图片对象(object) labels--标识(int32)
face_recognizer.train(features, labels)
#将训练文件保存
face_recognizer.save('face_trained.yml')
#face_recognizer.predict()
#对一个待测人脸图像进行判断, 寻找与当前图像距离最近的人脸图像。有两个返回值,label和confidence(置信度)
三、人脸识别
人脸识别主要依据是predict函数返回的confidence(置信度),数值越低越符合人物特征,这里我将低于80置信度的都视为本人,高于80则输出查无此人
names:是存储人物名字的一个list数组(ps:opencv的图相框似乎无法正确显示中文,中文会以?输出,笔者尝试了很久依没解决,据官方说在5.0版本会解决中文适配的问题)
def face_identify (img,names):
gray = cv2.cvtColor(img,cv2.COLOR_RGB2GRAY)
face_detect = cv2.CascadeClassifier(r"E:\python\Lib\site-packages\cv2\data\haarcascade_frontalface_alt2.xml")
face = face_detect.detectMultiScale(gray)
for x,y,w,h in face:
#矩形框外围
cv2.rectangle(img,(x,y),(x+w,y+h),color=(0,0,255),thickness=2)
#圆形框内部
cv2.circle(img,center = (x+w//2,y+h//2),radius = w//2,color= (0,255,0),thickness=1)
ids,confidence = face_recognizer.predict(gray[y:y+h,x:x+w])
if (confidence < 80):
cv2.putText(img,str(names[ids-1]),(x+10,y-10),cv2.FONT_HERSHEY_SIMPLEX,0.75,(0,255,0),1)
else:
cv2.putText(img, 'no person', (x + 10, y - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.75, (0, 255, 0), 1)
cv2.imshow('result',img)
cv2.waitKey(0)
最后,我们调用之前定义的函数来实现它
if __name__ =='__main__':
#创建一个的实例对象
face_recognizer = cv2.face.LBPHFaceRecognizer_create()
face_recognizer.read('face_trained.yml')
names = ['huge','xietingfen']
imgpath = r'C:\Users\yuehen\Desktop\img'
imagePaths = [os.path.join(imgpath, f) for f in os.listdir(imgpath)]
for i in imagePaths:
img = cv2.imread(str(i))
face_identify(img,names)
效果图:(如若侵权,请联系删除,谢谢,狗头保命)(源码文件见附件)
最后再返回视频导入模块,调用该函数就可以实现视频的识别了,当然,这里并没有通过验证、测试然后进行超参数优化,只是简单的训练后使用,效果是没有保障的,这也是后续需要学习实践的方向