人类区分不同的人脸是根据鼻子、醉、眼睛、眉毛、肤色等等因素,这些因素的大小、间距、形状的不同,构成了形形色色的人脸,也构成了这个大千世界。人脸识别的前期就是按照这个思路进行,即几何特征法。但后来发现这玩应儿并不好用,发展出了许许多多的识别方法。
如果人眼是根据鼻子、嘴巴这些组织的“特征”来区别人脸,那计算机可不可以按照其他格式的特征来区别人脸呢?答案是肯定的。基于面部器官的特征提取、基于模板的特征提取、基于代数方法的特征提取、基于弹性匹配法的特征提取等多重方法应用而生,具体的细节就不介绍了。
但是这个世界上有数十亿人,没有足够的特征点根本无法区分如此庞大的人群。利用深度学习(神经网络)可以得到合适的人脸特征值提取方法。深度学习通过百万千万级别的数据训练,可以自动的提取出那些适合计算机理解的和区分的人脸特征。现在有128、256、512、1024个特征的特征表。face_recognition采用的就是128特征表。
所有的人脸识别都基于一个基础,同一个人的人脸在不同的环境下所提取出的特征值大概相等。只要不带墨镜、口罩一类的遮挡物,我们在不同图像中所看到的人脸基本相同(P图过分的不算),计算机由相同的特征提取方法所提取出的特征值基本相等,而所对应在特征空间中的点应该非常接近,不同的人会离的非常远。
假设某两个点的距离小于某一阈值则认为是同一个人,大于这个阈值则认为是不同的人,通过所提取出的特征点就可以判断是否为同一人,这就是人脸识别的基本思想。阈值的具体数值需要通过大量的实验和工程经验来确定,在不同的环境下所对应的阈值是不同的。
face_recognition所采用的特征值提取方法与人的肤色无关。戴口罩或墨镜等掩饰物会使所提取到的特征值偏离真实的人脸,导致无法识别或者识别错误。而在具体的应用环境中,阈值可能会受到图像采集设备、人物所处环境的较大影响,最终影响识别的成功率。
此例为face_recognition官方给的示例,做了一些改动可以实时的检测人脸。
import cv2
import os
import face_recognition
import numpy
from PIL import Image
#新建文件夹来存储文件
def make_file():
if os.path.exists('image_data'):
pass
else:
os.makedirs('image_data')
#获取人物的信息
def get_message():
#打开摄像头
cap = cv2.VideoCapture(0)
#获得名字
name = str(input("please input your name"))
#创建图片存储路劲
new_path = 'image_data/' + name + '.jpg'
#启动LBP模型 识别人脸
face_cascade = cv2.CascadeClassifier("C://Users/lenovo/Desktop/opencv-files/lbpcascade_frontalface.xml")#打开LBP模型文件 需要提前下载文件 路径自行改动
while True:
ret, image = cap.read()
if ret:#如果成功捕获图像
cv2.putText(image, 'please look forward', (10, 20), cv2.FONT_HERSHEY_COMPLEX, 1.0, (255, 255, 255), 1)
gray = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY) # 转化为灰度图
faces = face_cascade.detectMultiScale(gray, 1.3, 5)
for (x, y, w, h) in faces:
cv2.rectangle(image, (x, y), (x + w, y + h), (255, 0, 0), 2)
if (len(faces) != 0):
cv2.imwrite(new_path, gray)
break
cv2.imshow('test2', image)
if cv2.waitKey(1) & 0xff == ord('q'):
break
cap.release()
cv2.destroyAllWindows()
return new_path, name
def get_image_encond(image_path, image_name):
image = face_recognition.load_image_file(image_path)
enconding_name = str(image_name) + '_face_encoding'
enconding_name = face_recognition.face_encodings(image)[0]
return enconding_name
人脸识别程序:
import cv2
import dlib
import face_recognition
from image_reserve import get_message, get_image_encond
from add_chinese import change_cv2_draw
import os
#打开摄像头
video_capture = cv2.VideoCapture(0)
#识别已有的图片 需要先下载奥巴马和拜登的图片
obama_image = face_recognition.load_image_file('C://Users/lenovo/Desktop/test-data/test1.jpg')#载入图片
obama_face_enconding = face_recognition.face_encodings(obama_image)[0]#将图片进行编码
biden_image = face_recognition.load_image_file('C://Users/lenovo/Desktop/test-data/test2.jpg')
biden_face_enconding = face_recognition.face_encodings(biden_image)[0]
#存入特征值
know_face_encondings = [
obama_face_enconding,
biden_face_enconding,
]
#匹配姓名
know_face_names = [
'OBAMA',
'Joe Biden',
]
#将新的人脸编码
new_image_path,new_name = get_message()
new_encon = (get_image_encond(new_image_path,new_name))
know_face_encondings.append(new_encon)
know_face_names.append(new_name)
face_locations = []
face_encondings = []
process_this_frame = True
#实时检测
while True:
#读取摄像头图像
ret, frame = video_capture.read()
#把图片变成原来的 1/4 大小 减少计算量 加快运行速率
small_frame =cv2.resize(frame, (0,0), fx=0.25, fy=0.25)
rgb_samll_frame = small_frame[:, :, ::-1]
if process_this_frame:
#在视频中找出所有的人脸 并将它们编码
face_locations = face_recognition.face_locations(rgb_samll_frame)
face_encondings = face_recognition.face_encodings(rgb_samll_frame, face_locations)
face_names = []
for face_enconding in face_encondings:
#跟已有的数据库进行查询
matches = face_recognition.compare_faces(know_face_encondings, face_enconding, tolerance=0.5)
name = 'unKnown'
if True in matches:
first_match_index = matches.index(True)
name = know_face_names[first_match_index]
face_names.append(name)
process_this_frame = not process_this_frame
for(top, right, bottom, left), name in zip(face_locations, face_names):
top *= 4
right *= 4
bottom *= 4
left *= 4
cv2.rectangle(frame, (left, top), (right, bottom), (0,0,255), 2) #画出边框
font = cv2.FONT_HERSHEY_DUPLEX
cv2.putText(frame, name, (left, top), font, 1.0, (255,255,255), 1)
frame = change_cv2_draw(frame, name, (left, top), 50, (255,0,0))
cv2.imshow('video', frame) #显示图像
if cv2.waitKey(1) & 0xff == ord('q'): #按下q 退出
break
video_capture.release()#关闭摄像头
cv2.destroyAllWindows()