概述
人脸识别作为一个热门项目,目前有多种方法实现,利用python和opencv来实现,是一个比较简单的项目。
1.环境配置
windows平台
python版本:3.8.6
pycharm版本:2019.1.2
Opencv版本:4.5.3
安装了python后,在命令行直接安装opencv库
pip install opencv-python
然后再去opencv官网,下载软件源码,如果下载速度过慢,可以选择网盘下载
2.实现思路
1.读取图片
2.灰度转换
3.修改图片大小
4.确定识别范围(脸)
5.实现人脸检测
6.多个目标的同时检测
7.对视频流实现检测
8.收集数据(录有带有人脸图片)
10.训练数据
11.实现人脸识别
3.具体实现
1.读取图片
#导入cv模块
import cv2 as cv
#读取图片
img = cv.imread('face1.jpg')
#显示图片
cv.imshow('show_img',img)
#等待,0表示无限等待后关闭窗口
cv.waitKey(0)
#释放内存
cv.destroyAllWindows()
cv的自带函数用起来很方便,imread,imshow函数等
2.灰度转换
#导入cv模块
import cv2 as cv
#读取图片
img = cv.imread('face2.jpg')
#灰度转换,使用到了cvt函数,其中img为图片参数,第二个为转换的颜色参数
gray_img = cv.cvtColor(img,cv.COLOR_BGR2GRAY)
#显示灰度图片
cv.imshow('gray_img',gray_img)
#保存灰度图片
cv.imwrite('gray_face2.jpg',gray_img)
#显示图片
cv.imshow('show_img',img)
#等待
cv.waitKey(0)
#释放内存
cv.destroyAllWindows()
3.修改图片大小
#导入cv模块
import cv2 as cv
#读取图片
img = cv.imread('face2.jpg')
#修改尺寸,使用到resize函数,参数为图片名和修改后的大小
resize_img = cv.resize(img,dsize=(200,200))
#显示原图
cv.imshow('img',img)
#显示修改后的
cv.imshow('resize_img',resize_img)
#打印原图尺寸大小
print('未修改:',img.shape)
#打印修改后的大小
print('修改后:',resize_img.shape)
#等待关闭窗口
while True:
if ord('g') == cv.waitKey(0):
break
#释放内存
cv.destroyAllWindows()
这一步中,我们可以自主选择是否关闭窗口,采用一个if语句,如果我们按下g键,关闭窗口
4.确定识别范围(脸)
#导入cv模块
import cv2 as cv
#读取图片
img = cv.imread('face2.jpg')
#坐标,确定识别的起始像素点位置坐标,识别的高度和宽度
x,y,w,h = 100,100,100,100
#绘制矩形,使用到rectangle函数,参数img为绘制的矩形位置和大小,边框颜色(bgr),边框粗细
cv.rectangle(img,(x,y,x+w,y+h),color=(0,0,255),thickness=2)
#绘制圆形,使用circle函数,参数为圆心,半径
cv.circle(img,center=(x+w,y+h),radius=100,color=(255,0,0),thickness=2)
#显示
cv.imshow('re_img',img)
while True:
if ord('g') == cv.waitKey(0):
break
#释放内存
cv.destroyAllWindows()
5.实现人脸检测
调用opencv训练好的分类器和自带的检测函数检测人脸人眼等的步骤简单直接:
1.加载分类器,当然分类器事先要放在工程目录中去。分类器本来的位置是在*opencvsourcesdatahaarcascades(harr分类器,也有其他的可以用,也可以自己训练)
2.调用detectMultiScale()函数检测,调整函数的参数可以使检测结果更加精确。
3.把检测到的人脸等用矩形(或者圆形等其他图形)画出来。
#导入cv模块
import cv2 as cv
#定义检测函数
def face_detect_demo():
#灰度转换
gary = cv.cvtColor(img,cv.COLOR_BGR2GRAY)
#加载调用opencv自带分类器cv.CascadeClassifier,减少训练成本
face_detect = cv.CascadeClassifier('D:/Opencv453/opencv/sources/data/haarcascades/haarcascade_frontalface_alt2.xml')
#调用函数,后两个参数表示检测的矩形范围。
face = face_detect.detectMultiScale(gary,1.01,5,0,(100,100),(300,300))
#绘制检测范围
for x,y,w,h in face:
cv.rectangle(img,(x,y),(x+w,y+h),color=(0,0,255),thickness=2)
cv.imshow('face_detect',img)
#读取图像
img = cv.imread('face2.jpg')
#检测函数
face_detect_demo()
#等待
while True:
if ord('g') == cv.waitKey(0):
break
#释放内存
cv.destroyAllWindows()
这一步采用了opencv自带的分类器,Haar特征分类器就是一个XML文件,该文件中会描述人体各个部位的Haar特征值。包括人脸、眼睛、嘴唇等等。加载分类器的步骤如下:
加载分类器cv.CascadeClassifier
找到opencv的安装目录,如下图
在har下提供大量的分类器
我们先把路径复制,粘贴到
再把我们需要使用的分类器的名称复制
粘贴到
再把路径中的符号更改
同时使用到opencv中的face_detect.detectMultiScale函数
总共有5个参数
1.image表示的是要检测的输入图像(一般为灰度图,加快检测速度)
2.objects表示检测到的人脸目标序列,检测物体的矩形框向量组
3.scaleFactor表示每次图像尺寸减小的比例
4. minNeighbors表示每一个目标至少要被检测到n次才算是真的目标(因为周围的像素和不同的窗口大小都可以检测到人脸),
5.默认为0
6.minSize为目标的最小尺寸
7.minSize为目标的最大尺寸
改变上面的2,3,4参数,可以让检测到的人脸矩形框更准确
6.多个目标的同时检测
#导入cv模块
import cv2 as cv
#检测函数
def face_detect_demo():
#灰度转换
gary = cv.cvtColor(resize_img,cv.COLOR_BGR2GRAY)
face_detect = cv.CascadeClassifier('D:/Opencv453/opencv/sources/data/haarcascades/haarcascade_frontalface_default.xml')
face = face_detect.detectMultiScale(gary)
for x,y,w,h in face:
cv.rectangle(resize_img,(x,y),(x+w,y+h),color=(0,0,255),thickness=2)
cv.imshow('multi_face_detect',resize_img)
img = cv.imread('duoren.jpg')
resize_img = cv.resize(img,dsize=(2048,1024))
print('未修改:',img.shape)
print('修改后:',resize_img.shape)
#检测函数
face_detect_demo()
#等待
while True:
if ord('g') == cv.waitKey(0):
break
#释放内存
cv.destroyAllWindows()
此步导入多目标图片即可
7.对视频流实现检测
#导入cv模块
import cv2 as cv
#检测函数
def face_detect_demo(img):
gary = cv.cvtColor(img,cv.COLOR_BGR2GRAY)
face_detect = cv.CascadeClassifier('D:/Opencv453/opencv/sources/data/haarcascades/haarcascade_frontalface_default.xml')
face = face_detect.detectMultiScale(gary)
for x,y,w,h in face:
cv.rectangle(img,(x,y),(x+w,y+h),color=(0,0,255),thickness=2)
cv.imshow('result',img)
#读取摄像头,参数为0,调用默认摄像头
#cap = cv.VideoCapture(0)
#读取视频,按帧数读取
cap = cv.VideoCapture("test1.mp4")
#循环
while True:
#调用cap.read函数
flag,frame = cap.read()
if not flag:
break
face_detect_demo(frame)
if ord('g') == cv.waitKey(1):
break
#释放内存
cv.destroyAllWindows()
#释放摄像头
cap.release()
8.收集数据(录有带有人脸图片)
#导入模块
import cv2
#摄像头
cap=cv2.VideoCapture(0)
falg = 1
num = 1
while(cap.isOpened()):#检测是否在开启状态
ret_flag,Vshow = cap.read()#得到每帧图像
cv2.imshow("Capture_Test",Vshow)#显示图像
k = cv2.waitKey(1) & 0xFF#按键判断
if k == ord('s'):#保存
cv2.imwrite("E:/PycharmProjects/facer/opencv/data/facedata/"+str(num)+".lumengyun"+".jpg",Vshow)
print("success to save"+str(num)+".jpg")
print("-------------------")
num += 1
elif k == ord(' '):#退出
break
#释放摄像头
cap.release()
#释放内存
cv2.destroyAllWindows()
#将人脸照片保存后,后续可以通过特征提取,识别人脸
当然,也可以直接将数据把保存在待训练数据集data里
10.训练数据
这一步就是将前面几步录入人脸数据进行训练,通过将人脸特征和人脸的ID对应起来,完成人脸识别,每张图片都有一个ID
在data里面的facedata作为我们的待训练数据,获取到facedata
使用函数getImageAndLabels,得到图片的特征faces和ID(ids)
再用cv2.face.LBPHFaceRecognizer_create()函数,得到训练对象。
FaceRecognizer类,里面有相关的一些人脸识别的算法及函数接口
LBP是一种特征提取方式,能提取出图像的局部的纹理特征,最开始的LBP算子是在3X3窗口中,取中心像素的像素值为阀值,与其周围八个像素点的像素值比较,若像素点的像素值大于阀值,则此像素点被标记为1,否则标记为0。这样就能得到一个八位二进制的码,转换为十进制即LBP码,于是得到了这个窗口的LBP值,用这个值来反映这个窗口内的纹理信息。LBPH是在原始LBP上的一个改进,在opencv支持下我们可以直接调用函数直接创建一个LBPH人脸识别的模型。
再利用我们recognizer对象.去训练整合(train)之前得到的图像特征和图像ID(faces,np.array(ids))
最后将训练后的数据(向量)保存到trainer.yml,以后进行人脸识别,直接调用这个文件就可以了
函数getImageAndLabels的实现原理
首先先建立数组来存储需要的人脸特征相关数据和ID相关数据
再把所有的信息通过路径存储在IMagePaths中
加载分类器
再对上面保存的所有信息,进行一个遍历读取 for imagePath in imagePaths:
首先
#打开图片,以灰度化方式打开。PIL_img=Image.open(imagePath).convert('L')
PIL有九种不同模式:1,L,P,RGB,RGBA,CMYK,YCbCr,I,F
#图片以灰度表示后,就是用数字来表示,这时候对它进行向量化,将图像转换为数组,以黑白深浅 。img_numpy=np.array(PIL_img,'uint8')
#获取图片人脸特征 。faces = face_detector.detectMultiScale(img_numpy)
#获取每张图片的id和姓名 id = int(os.path.split(imagePath)[1].split('.')[0])
#这里要注意预防无面容照片
for x,y,w,h in faces:
ids.append(id)
facesSamples.append(img_numpy[y:y+h,x:x+w])
#打印脸部特征和id。print('id:', id),print('fs:', facesSamples)
最后将这些遍历的数据,全部都return到faces和ids中,得到全部训练后的数据集
import os
import cv2
import sys
from PIL import Image
import numpy as np
def getImageAndLabels(path):
facesSamples=[]
ids=[]
imagePaths=[os.path.join(path,f) for f in os.listdir(path)]
#检测人脸
face_detector = cv2.CascadeClassifier('D:/Opencv453/opencv/sources/data/haarcascades/haarcascade_frontalface_alt2.xml')
#打印数组imagePaths
print('数据排列:',imagePaths)
#遍历列表中的图片
for imagePath in imagePaths:
#打开图片,灰度化。PIL有九种不同模式:1,L,P,RGB,RGBA,CMYK,YCbCr,I,F
PIL_img=Image.open(imagePath).convert('L')
# PIL_img = cv2.resize(PIL_img, dsize=(400, 400))
# 向量化,将图像转换为数组,以黑白深浅
img_numpy=np.array(PIL_img,'uint8')
#获取图片人脸特征
faces = face_detector.detectMultiScale(img_numpy)
#获取每张图片的id和姓名
id = int(os.path.split(imagePath)[1].split('.')[0])
#预防无面容照片
for x,y,w,h in faces:
ids.append(id)
facesSamples.append(img_numpy[y:y+h,x:x+w])
#打印脸部特征和id
#print('fs:', facesSamples)
print('id:', id)
#print('fs:', facesSamples[id])
print('fs:', facesSamples)
#print('脸部例子:',facesSamples[0])
#print('身份信息:',ids[0])
return facesSamples,ids
if __name__ == '__main__':
#图片路径
path='./data/facedata/'
#获取图像数组和id标签数组和姓名
faces,ids=getImageAndLabels(path)
#获取训练对象
recognizer=cv2.face.LBPHFaceRecognizer_create()
#recognizer.train(faces,names)#np.array(ids)
recognizer.train(faces,np.array(ids))
#保存文件
recognizer.write('trainer/trainer.yml')
#save_to_file('names.txt',names)
此步是核心,决定人脸识别的准确与否,
11.实现人脸识别
将我们训练后存放在yml文件中的数据,导入到recognizer中,用这个文件来判断我们脸部特征是否符合,给出可执行评分
name = [] 存放我们训练数据图片文件名中,第一个.后面的字符,定义为名字
face_detect_demo中和上面的作用差不多,先把图片灰度化,然后加载分类器,然后进行检测,将整张图片中的人脸部分框起来,这部分就是我们得到的人脸照片。
得到的人脸照片,我们需要进行一个预测评分recoginzer.predict,得到的评分就是confidence
根据这个评分,来进行人脸识别,如果confidence过大,说明程序没有对这个人脸进行训练,无法通过验证,给出unknown提示
confidence未达到预警值,说明这个人脸被我们识别过,这是把上一步中训练识别得到的name打到矩形框上,给出人名。
import cv2
import numpy as np
import os
# coding=utf-8
import urllib
import urllib.request
import hashlib
# 加载训练数据集文件
recognizer = cv2.face.LBPHFaceRecognizer_create()
recoginzer.read('trainer/trainer.yml')
# 名称
names = []
warningtime = 0
# 准备识别的图片
def face_detect_demo(img):
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) # 转换为灰度
face_detector = cv2.CascadeClassifier(
'D:/Opencv453/opencv/sources/data/haarcascades/haarcascade_frontalface_alt2.xml')
face = face_detector.detectMultiScale(gray, 1.1, 5, cv2.CASCADE_SCALE_IMAGE, (100, 100), (300, 300))
# face=face_detector.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 = recoginzer.predict(gray[y:y + h, x:x + w])
# print('标签id:',ids,'置信评分:', confidence)
if confidence > 80:
global warningtime
warningtime += 1
if warningtime > 100:
warningtime = 0
cv2.putText(img, 'unkonw', (x + 10, y - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.75, (0, 255, 0), 1)
else:
cv2.putText(img, str(names[ids - 1]), (x + 10, y - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.75, (0, 255, 0), 1)
cv2.imshow('result', img)
# print('bug:',ids)
def name():
path = './data/facedata/'
# names = []
imagePaths = [os.path.join(path, f) for f in os.listdir(path)]
for imagePath in imagePaths:
name = str(os.path.split(imagePath)[1].split('.', 2)[1])
names.append(name)
cap = cv2.VideoCapture(0)
name()
while True:
flag, frame = cap.read()
if not flag:
break
face_detect_demo(frame)
if ord(' ') == cv2.waitKey(10):
break
cv2.destroyAllWindows()
cap.release()
# print(names)
最后
以上就是健康纸鹤为你收集整理的基于opencv的人脸识别和检测1.环境配置的全部内容,希望文章能够帮你解决基于opencv的人脸识别和检测1.环境配置所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复