match_face/.venv/Lib/site-packages/face_recognition_util/FaceUtil.py

148 lines
4.9 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import face_recognition
import numpy as np
import cv2
import base64
from PIL import Image, ImageDraw, ImageFont
class FaceNotFoundException(Exception):
def __init__(self):
err = "Compare Failure,cannot find face in image"
Exception.__init__(self, err)
# base64转opencv图片
def convert_to_image(base64_code):
"""
base64转图片
:param base64_code:需要转换的base64码:
:return image:openCv格式图片:
"""
# base64解码
b64image = base64.b64decode(base64_code)
# 转opencv图片
image_array = np.frombuffer(b64image, np.uint8)
result_image = cv2.imdecode(image_array, cv2.COLOR_BGR2RGB)
# 返回opencv图片对象
if result_image is None:
return "error"
else:
return result_image
# 缩放图片
def resize_image(image, multiple=1.0):
"""
缩放图片
:param image:需要缩放的图片:
:param multiple:可选缩放倍数,默认120大小基准缩放:
:return:
"""
# 默认以基准120大小等比例缩小
base_height = 120
image_height = image.shape[0]
if multiple == 1:
multiple = base_height / image_height
result_image = cv2.resize(image, (0, 0), fx=multiple, fy=multiple)
return result_image
# 获取单个人脸128特征点向量
def get_face_encoding(face_image, face_locations=None):
"""
获取人脸特征点向量
:param face_image: 已知人脸图片:
:param face_locations: 人脸位置:
:return face_encoding: 人脸特征点向量:
"""
face_encoding = face_recognition.face_encodings(face_image, face_locations)
return face_encoding
# 人脸比对
def contrast_faces(known_image, unknown_image, tolerance=0.4):
"""
人脸比对
:param known_image: 已知图片:
:param unknown_image: 待检测图片:
:param tolerance: 检测基准,数值越小结果越精确,同时可能出现比对失败:
:return result:检测结果:
"""
# noinspection PyBroadException
try:
known_image_encoding = get_face_encoding(resize_image(known_image))[0]
unknown_image_encoding = get_face_encoding(resize_image(unknown_image))[0]
result = face_recognition.compare_faces([known_image_encoding], unknown_image_encoding, tolerance)
return result
except IndexError:
return "nf"
except Exception as e:
print("recognition error\n cause{}".format(e))
return "err"
# 摄像头实时比对
def real_time_comparison(known_face_encodings, known_face_names, tolerance=0.4):
"""
人脸实时比对
:param known_face_encodings:已知人脸特征点向量数组:
:param known_face_names:已知人脸名称:
:param tolerance:检测基准,数值越小结果越精确,同时可能出现比对失败:
:return None:无返回值:
"""
process_this_frame = True
face_locations = ""
face_names = ""
cap = cv2.VideoCapture(0)
while True:
ret, frame = cap.read()
frame = cv2.flip(frame, 1, dst=None)
small_frame = resize_image(frame, 0.5)
rgb_small_frame = small_frame[:, :, ::-1]
if process_this_frame:
face_locations = face_recognition.face_locations(rgb_small_frame)
face_encodings = get_face_encoding(rgb_small_frame, face_locations)
face_names = []
for face_encoding in face_encodings:
matches = face_recognition.compare_faces(known_face_encodings, face_encoding, tolerance)
name = "Unknown"
mmax_index = matches.index(max(matches))
mmax_value = matches[mmax_index]
for index, match in enumerate(matches):
matches[index] = False
if mmax_value > (1-tolerance)*100:
matches[mmax_index] = True
if True in matches:
first_match_index = matches.index(True)
name = known_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 *= 2
right *= 2
bottom *= 2
left *= 2
cv2.rectangle(frame, (left - 10, top - 10), (right + 10, bottom + 10), (0, 0, 255), 1)
cv2.rectangle(frame, (left, bottom - 20), (right, bottom), (0, 0, 100), cv2.FILLED)
cv2_im = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
pil_im = Image.fromarray(cv2_im)
draw = ImageDraw.Draw(pil_im)
font = ImageFont.truetype("simhei.ttf", 25, encoding="utf-8")
draw.text((left + 20, bottom - 25), name, (255, 255, 255), font=font)
frame = cv2.cvtColor(np.array(pil_im), cv2.COLOR_RGB2BGR)
cv2.imshow('Video', frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
cap.release()
cv2.destroyAllWindows()