人脸识别作为一个热门项目,目前有多种方法实现,利用python和opencv来实现,是一个比较简单的项目。
1.环境配置
windows平台
python版本:3.8.6
pycharm版本:2019.1.2
Opencv版本:4.5.3
安装了python后,在命令行直接安装opencv库
1pip install opencv-python
然后再去opencv官网,下载软件源码,如果下载速度过慢,可以选择网盘下载
2.实现思路
1.读取图片
2.灰度转换
3.修改图片大小
4.确定识别范围(脸)
5.实现人脸检测
6.多个目标的同时检测
7.对视频流实现检测
8.收集数据(录有带有人脸图片)
10.训练数据
11.实现人脸识别
3.具体实现
1.读取图片
1
2
3
4
5
6
7
8
9
10#导入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.灰度转换
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16#导入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.修改图片大小
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20#导入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.确定识别范围(脸)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17#导入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.把检测到的人脸等用矩形(或者圆形等其他图形)画出来。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24#导入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.多个目标的同时检测
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23#导入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.对视频流实现检测
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28#导入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.收集数据(录有带有人脸图片)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24#导入模块 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])
#这里要注意预防无面容照片
1
2
3for 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中,得到全部训练后的数据集
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50import 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打到矩形框上,给出人名。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61import 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内容请搜索靠谱客的其他文章。
发表评论 取消回复