python使用opencv摄像头识别特定人脸,并启动语音问候

"""

==================== 训练脸部数据  ==================

"""

学习要有一种空杯的心态,先跟着来---------------------------------->>>

一、准备脸部图片:

我们将要检测的脸部图片命名为"姓名_数字编号.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)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章