1、提出问题
通过python+opencv实现对摄像头输入的图像实时人脸识别,或者对输入的图片进行人脸识别
2、解决思路
本项目主要有两个模块:数据训练和人脸识别
1.1 数据训练
数据训练模块的思路如下:
(1)定义getImageAndLabels()用来返回训练图像的脸部数据和图像文件名中的顺序数据:
faces和ids
(2)创建、加载识别器recognizer
(3)对faces和np.array(ids)进行训练:recognizer.train(faces, np.array(ids))
(4)训练好的数据存储在trainer.yml下,便于人脸识别模块调用
1.2 人脸识别
人脸识别模块的思路如下:
(1)加载数据训练模块的训练数据
(2)加载opencv提供的人脸分类器
(3)定义face_detect_demo()方法获取需要识别的图片上的人脸并在脸部绘制方框,把方框内部的人脸数据与trainer.yml中的数据对比,返回trainer.yml文件中相似图片数据的id和confidence
(4)定义name()方法获取训练图片的人名,以便于对识别出的图片中的人脸做标记
(5)将摄像头捕捉的图像抽帧传入face_detect_demo()实时识别并在图片上显示结果
3、代码
3.1 数据训练模块代码
import os
import cv2 as cv
import numpy as np
from PIL import Image
def getImageAndLabels(path):
#储存人脸信息
facesSamples = []
#储存序号数据
ids = []
#储存姓名信息
names = []
#储存图片信息
imagePaths = []
# 得到文件名中的人名
# listdir列出文件夹下的文件
for file in os.listdir(path):
if file.endswith('jpg'):
# 路径拼接,imagePath是图片的绝对路径
imagePath = os.path.join(path, file)
# 将图片路径添加到列表中
imagePaths.append(imagePath)
#加载分类器
face_detector = cv.CascadeClassifier('D:/Software/opencv/opencv/sources/data/haarcascades/haarcascade_frontalface_alt2.xml')
#id从0开始
id = 1
#遍历imagePaths中存储的绝对路径对应的图片
for imagePath in imagePaths:
#打开图片,灰度化PIL有九种不同模式,其中1为黑白,L为灰度
PIL_img = Image.open(imagePath).convert('L')
#将图像转换成数组,以黑白深浅
img_numpy = np.array(PIL_img,'uint8')
#获取图片人脸特征
faces = face_detector.detectMultiScale(image=img_numpy,scaleFactor=1.01,minNeighbors=5,minSize=(180,180),maxSize=(300,300))
# 得到图片绝对路径列表中的人名,存储在names列表
name = (os.path.split(imagePath)[1].split('-')[1]).split('.')[0]
#预防无面容照片
for x,y,w,h in faces:
names.append(name)
ids.append(id)
facesSamples.append(img_numpy[y:y+h,x:x+w])
#打印脸部特征和id
print('id:',id)
print('name:',name)
print('fs',img_numpy[y:y+h,x:x+w])
# id自增1
id += 1
print(ids)
print(names)
return facesSamples,ids
if __name__ == '__main__':
#图片的路径
path = 'D:/SoftwareCache/PyCharmCache/Project_Face/trainer/faces'
#获取图像数组和id标签数组和姓名
faces,ids = getImageAndLabels(path)
#加载识别器
recognizer = cv.face.LBPHFaceRecognizer_create()
#训练
recognizer.train(faces, np.array(ids))
print(ids)
#保存文件
recognizer.write('./trainer.yml')
3.2 人脸识别模块代码
import cv2 as cv
import os
import numpy as np
from PIL import Image
import urllib
import urllib.request
#加载训练数据集文件
recognizer = cv.face.LBPHFaceRecognizer_create()
#加载数据
recognizer.read('./trainer.yml')
#名字
names = []
#警报全局变量
warningtime = 0
face_detector = cv.CascadeClassifier('D:/Software/opencv/opencv/sources/data/haarcascades/haarcascade_frontalface_default.xml')
#准备识别的图像
def face_detect_demo(img):
gray = cv.cvtColor(img,cv.COLOR_BGR2GRAY)#转换为灰度
#加载官方人脸识别器
face_detector = cv.CascadeClassifier('D:/Software/opencv/opencv/sources/data/haarcascades/haarcascade_frontalface_alt2.xml')
#在gray图上找出人脸
face = face_detector.detectMultiScale(gray,1.01,5,cv.CASCADE_SCALE_IMAGE,(180,180),(300,300))
for x,y,w,h in face:
#在img上面绘制脸部方框
cv.rectangle(img,(x,y),(x+w,y+h),color=(0,0,255),thickness=1)
#img上绘制脸部圆圈
cv.circle(img,center=(x+w//2,y+h//2),radius=w//2,color=(0,255,0),thickness=1)
#人脸识别
ids,confidence = recognizer.predict(gray[y:y+h,x:x+w])
print(ids)
print('confidence:',confidence)
print('name:',names[ids-1])
if confidence > 120:
#gloal声明一个全局变量
global warningtime
warningtime += 1
if warningtime > 100:
#不是存储在数据库中的人脸,图片上打印:unknown
#
#
cv.putText(img,'unknown',(x,y+15),cv.FONT_HERSHEY_SIMPLEX,0.75,(0,255,0),1)
else:
cv.putText(img,str(names[ids-1]),(x,y+15),cv.FONT_HERSHEY_SIMPLEX,0.75,(0,255,0),1)
cv.imshow('result',img)
def name():
imagePaths = []
path = './faces'
for file in os.listdir(path):
if file.endswith('jpg'):
# 路径拼接,imagePath是图片的绝对路径
imagePath = os.path.join(path, file)
# 将图片路径添加到列表中
imagePaths.append(imagePath)
#得到图片文件名中的名字
for imagePath in imagePaths:
# 打开图片,灰度化PIL有九种不同模式,其中1为黑白,L为灰度
PIL_img = Image.open(imagePath).convert('L')
# 将图像转换成数组,以黑白深浅
img_numpy = np.array(PIL_img, 'uint8')
# 获取图片人脸特征
faces = face_detector.detectMultiScale(image=img_numpy, scaleFactor=1.01, minNeighbors=5, minSize=(180, 180),
maxSize=(300, 300))
# 得到图片绝对路径列表中的人名,存储在names列表
name = (os.path.split(imagePath)[1].split('-')[1]).split('.')[0]
# 预防无面容照片
for x, y, w, h in faces:
names.append(name)
# 打印脸部特征和id
print('id:', id)
print('name:', name)
print('fs', img_numpy[y:y + h, x:x + w])
print(names)
cap = cv.VideoCapture(0)
name()
# #以图片做实验
# #D:\SoftwareCache\PyCharmCache\Project_Face\trainer\FERET_80_80\FERET_80_80-人脸数据库\FERET-001-Lesley
#
# frame = cv.imread('./face8.jpg')
# face_detect_demo(frame)
#
# while True:
# if ord('q') == cv.waitKey(0):
# break
#
# cv.destroyAllWindows()
#以摄像头捕捉图像做实验
while True:
flag,frame = cap.read()
if not flag:
break
face_detect_demo(frame)
if ord(' ') == cv.waitKey(10):
break
cv.destroyAllWindows()
cap.release()
4、结果如下
5、声明
此篇博客为笔者学习B站python+opencv人脸识别项目后自己的一点总结,侵权请联系笔者删除。
B站视频链接:一天搞定人脸识别项目!学不会up直接下跪!(python+opencv)_哔哩哔哩_bilibilihttps://www.bilibili.com/video/BV1Lq4y1Z7dm?spm_id_from=333.999.0.0