"""
==================== 训练脸部数据 ==================
"""
学习要有一种空杯的心态,先跟着来---------------------------------->>>
一、准备脸部图片:
我们将要检测的脸部图片命名为"姓名_数字编号.jpg"的形式,注意编号不连续,创建一个facePics文件夹专门放图片的。
完整代码如下:
# 训练脸部数据 ===============================================
print('*'*50)
print('\t'*5,'训练脸部数据程序')
print('*'*50)
import os
import cv2 as cv
import numpy as np
from PIL import Image
# 检查图片数据是否存在
array_of_img = []
def read_directory(directory_name):
for filename in os.listdir(directory_name):
img = cv.imread(directory_name + "/" + filename)
array_of_img.append(img)
# 图片文件夹
directory = os.getcwd()+'\\facePics'
read_directory(directory)
count = len(array_of_img)
if count == 0:
print('facePics文件夹下不存在用于训练的图片,将退出!')
input('按任意键退出')
quit()
print('开始训练数据...')
# 人脸检测器
face_detector=cv.CascadeClassifier('haarcascade_frontalface_default.xml')
# 获取训练图片和对应的标签id
def getImageAndLabels(path):
# 人脸区域数组
faceSamples=[]
# 图像id数组
ids=[]
# 合并图片全路径名称存入列表
imgPaths=[os.path.join(path,f) for f in os.listdir(path)]
#print(imgPaths)
# 遍历列表中的图片
for impath in imgPaths:
# 打开图片
PIL_img=Image.open(impath).convert('L') # 转为灰度图
# 将图像转换为数组
img_numpy=np.array(PIL_img,'uint8')
# 将面部图片数组传入检测器,获取人脸数据
faces=face_detector.detectMultiScale(img_numpy)
# 获取每张图片的id
splitStr = os.path.split(impath) # 切分路径
#print(splitStr) # ('C:\\Users\\Administrator\\Desktop\\python学习笔记\\facePics', '小明_1.jpg')
idStr = splitStr[1].split('.')[0]
idStr = idStr.split('_')[1] # 小明_1
id = int(idStr)
for x,y,w,h in faces:
# 提取人脸
faceSamples.append(img_numpy[y:y+h,x:x+w]) # 二维数组切片:获取y:y+h行,x:x+w列
ids.append(id)
return faceSamples,ids
if __name__=='__main__':
# 图片路径
path='facePics'
# 获取图像数组和id标签数组
faces, ids = getImageAndLabels(path)
# 获取训练对象
recognizer = cv.face.LBPHFaceRecognizer_create() # 注:如果报错可能因为未安装contrib(用于训练数据),尝试pip install opencv-contrib-python
# 训练数据
recognizer.train(faces,np.array(ids)) # train(面部数据,图片id数组)
# 保存文件
recognizer.write('trainer.yml')
print('脸部数据 trainer.yml 训练成功')
input('按任意键退出')
quit()
如果你的机器环境都OK,且程序无误,那么运行上述代码将会生成trainer.yml数据文件。
"""
=================== 摄像头识别并发出问候音 ==================
"""
二、找一台有摄像头的机器,运行以下代码,将开启人脸识别模式
完整代码如下:
# 检测视频人脸 ========================================================================
import os
from win32com.client import Dispatch
print(os.getcwd()) # 获得当前目录
print('================================= 人脸识别程序 ==============================')
_input=input('按任意键开始!')
# 检查训练数据是否存在
exist = os.path.exists(os.getcwd()+'\\trainer.yml');
if not exist: # 文件不存在
print('训练数据 trainer.yml 不存在,系统将退出!')
input('请按任意键退出')
quit()
# 获取所有图片的id和对应名称
names={}
#{1:'贝提',1:'鲁姆',1:'杰米',1:'大卫',1:'米妮'}
def getNamesDic(imgPaths):
for impath in imgPaths:
# 获取每张图片的id
splitStr = os.path.split(impath) # 切分路径
#print(splitStr) # ('C:\\Users\\Administrator\\Desktop\\python学习笔记\\facePics', '小明_1.jpg')
fulnam = splitStr[1].split('.')[0] # 小明_1
idStr = fulnam.split('_')[1] # 1
nam = fulnam.split('_')[0] # 小明
id = int(idStr)
names[id] = nam
imgPaths = []
def read_directory(directory_name):
for filename in os.listdir(directory_name):
picname = directory_name + "/" + filename
imgPaths.append(picname)
# 图片文件夹
directory = os.getcwd()+'\\facePics'
read_directory(directory)
getNamesDic(imgPaths)
# 使用文字转语音功能,发出问候音:xx,你好!
def welcome(id):
msg='你好,'+str(id)
speaker=Dispatch('SAPI.SpVoice')
speaker.Speak(msg)
del speaker
# cv2.VideoCapture(0)代表调取摄像头资源,其中0代表电脑摄像头,1代表外接摄像头(usb摄像头)
# cap.read()按帧读取视频,ret,frame是获cap.read()方法的两个返回值。其中ret是布尔值,
# 如果读取帧是正确的则返回True,如果文件读取到结尾,它的返回值就为False,如果没有摄像头则返回False。frame就是每一帧的图像,是个三维矩阵。
print('正在打开摄像头...')
cap = cv.VideoCapture(0) # 调用自己的摄像头
ret,frame = cap.read()
if not ret:
cap = cv.VideoCapture(1)
ret,frame = cap.read()
if not ret:
print('未发现电脑摄像头,或未能打开摄像头,将进行本地视频人脸识别') # False
cap = cv.VideoCapture('video.mkv')
ret,frame = cap.read()
if not ret:
quit()
def face_detect_demo(img):
#print(type(img)) # <class 'numpy.ndarray'>
# 将图片灰度
gray = cv.cvtColor(img,cv.COLOR_BGR2GRAY)
# 加载训练数据集文件
recognizer = cv.face.LBPHFaceRecognizer_create()
recognizer.read('trainer.yml')
# 加载特征数据
# 'D:\\opencv_3.4.7\\opencv\\sources\\data\\haarcascades\\haarcascade_frontalface_default.xml'
#
face_detector = cv.CascadeClassifier('haarcascade_frontalface_default.xml')
faces = face_detector.detectMultiScale(gray)
for x,y,w,h in faces:
cv.rectangle(img,(x,y),(x+w,y+h),color=(0,0,255),thickness=2)
# 识别是哪一个
id,confidence=recognizer.predict(gray[y:y+h,x:x+w])
# 播放欢迎语音...
if confidence<50:
print('标签id:',id,' 置信评分:',confidence,end='\t')
print('你好,',names[id])
# 在人脸下画一个有名字的标签;cv2.putText 不支持中文所以这里换一种方法
cv.putText(img, str(id), (x,y), cv.FONT_HERSHEY_SIMPLEX, 1.0, (255, 255, 255), 1) # 图像,文字内容, 坐标 ,字体,大小,颜色,字体厚度
##font=ImageFont.truetype('msyh.ttc',20) # 微软雅黑20号字体,此处未指定路径会从Windows字体目录查找
##img_pil = Image.fromarray(img)
##draw = ImageDraw.Draw(img_pil)
##d#raw.text( (x,y), names[id], font=font, fill=(255, 255, 255))
##frame = np.array(img_pil)
welcome(names[id])
cv.imshow('result',img)
print('加载人脸特征数据...')
while True:
flag,frame=cap.read()
#print('flag: ',flag,'frame.shape: ',frame.shape) # flag: True frame.shape: (720, 1280, 3)
if not flag:
break
# 将视频帧的大小调整为1/2以加快人脸识别处理
#frame = cv.resize(frame, (0, 0), fx=0.5, fy=0.5)
face_detect_demo(frame)
if ord('q') == cv.waitKey(10):
break
cv.destroyAllWindows() # 释放内存
cap.release() # 清理空间
如果摄像头识别到相似度高的人脸,将启动问候音:“xx,你好!”
特别注意:安装的opencv的版本和python的版本都需要考虑到,不然会很麻烦!我们需要将脸部数据特征xml文件,和训练出来的数据yml文件放好位置;
最后链接附上源码和相关资源
注:(由于CSDN有上传文件大小限制,我打包好的exe可执行程序就不上传了,需要加微信:2463954659)