Files
2024-04-13 22:06:43 +08:00

163 lines
6.0 KiB
Python

from tensorflow.keras.preprocessing.image import img_to_array
from tensorflow.keras.models import load_model
import numpy as np
import pickle
import cv2
import time
import os
def resize(image, width=None, height=None, inter=cv2.INTER_AREA):
dim = None
(h, w) = image.shape[:2]
# 如果高和宽为None则直接返回
if width is None and height is None:
return image
# 检查宽是否是None
if width is None:
# 计算高度的比例并并按照比例计算宽度
r = height / float(h)
dim = (int(w * r), height)
# 高为None
else:
# 计算宽度比例,并计算高度
r = width / float(w)
dim = (width, int(h * r))
resized = cv2.resize(image, dim, interpolation=inter)
# return the resized image
return resized
# 构建脸部/活体识别检测器
class Face_inference():
def __init__(self):
self.face_detector_path = "./models/face_detector/"
self.recognize_embed_path = "./models/nn4.small2.v1.t7"
self.liveness_model_path = "./models/liveness.model"
self.recognize_pickle = "./pickles/face_label/recognizer.pickle"
self.recognize_class_pickle = "./pickles/face_label/le.pickle"
self.liveness_class_pickle = "./pickles/liveness/le.pickle"
# 人脸检测
self.face_detector = cv2.dnn.readNetFromCaffe(
self.face_detector_path + "deploy.prototxt",
self.face_detector_path + "res10_300x300_ssd_iter_140000.caffemodel"
)
# 人脸embedding
self.face_embed_model = cv2.dnn.readNetFromTorch(self.recognize_embed_path)
# embedding SVM 分类
with open(self.recognize_pickle,"rb") as f:
self.face_recog_model = pickle.loads(f.read())
# 活体分类
self.liveness_model = load_model(self.liveness_model_path)
# 对应类别标签
# 人脸类别
with open(self.recognize_class_pickle,"rb") as f:
self.face_class = pickle.loads(f.read()).classes_
# 活体类别
with open(self.liveness_class_pickle,"rb") as f:
self.liveness_class = pickle.loads(f.read()).classes_
def face_detect(self,img,conf_threshold = 0.1,is_show = False):
if img is None:
return img
frame = resize(img,width = 600)
h,w = frame.shape[:2]
blob = cv2.dnn.blobFromImage(
cv2.resize(frame,(300,300)),1.0,(300,300),
(104.0,177.0,123.0),swapRB = False,crop = False
)
self.face_detector.setInput(blob)
detections = self.face_detector.forward()
for i in range(detections.shape[2]):
conf = detections[0,0,i,2]
if conf > conf_threshold:
iou = detections[0,0,i,3:7] * np.array([w,h,w,h])
(start_x,start_y,end_x,end_y) = iou.astype('int')
face = frame[start_y:end_y,start_x:end_x]
fh,fw = face.shape[:2]
if fh < 20 or fw < 20:
continue
face_blob = cv2.dnn.blobFromImage(
face,1.0/255.,(96,96),
(0,0,0),swapRB = True , crop = False
)
self.face_embed_model.setInput(face_blob)
vec = self.face_embed_model.forward()
preds = self.face_recog_model.predict_proba(vec)[0]
pred_index = np.argmax(preds)
pred_class,pred_prob = self.face_class[pred_index],preds[pred_index]
pred_class = pred_class if pred_prob > conf_threshold else "err"
if is_show:
text = f"{pred_class}: {pred_prob*100:.2f}%"
cv2.rectangle(frame,(start_x,start_y),(end_x,end_y),
(0,0,255,2))
y = start_y - 10 if start_y - 10 > 10 else start_y + 10
cv2.putText(frame,text,(start_x,y),cv2.FONT_HERSHEY_SIMPLEX, 0.45, (0, 0, 255), 2)
return pred_class,pred_prob,frame
else:
return pred_class,pred_prob
def live_detect(self,img,name = "",conf_threshold = 0.1,is_show = False):
if img is None:
return img
frame = resize(img,width=600)
h,w = frame.shape[:2]
blob = cv2.dnn.blobFromImage(
cv2.resize(frame,(300,300)),1.0,(300,300),
(104.0,177.0,123.0),swapRB = False,crop = False
)
self.face_detector.setInput(blob)
detections = self.face_detector.forward()
for i in range(detections.shape[2]):
conf = detections[0,0,i,2]
if conf > conf_threshold:
iou = detections[0,0,i,3:7] * np.array([w,h,w,h])
(start_x,start_y,end_x,end_y) = iou.astype('int')
face = frame[start_y:end_y,start_x:end_x]
face = cv2.resize(face,(32,32))
face = face.astype('float')/255.
face = img_to_array(face)
face = np.expand_dims(face,axis = 0)
preds = self.liveness_model(face)[0]
index = np.argmax(preds)
pred_class,pred_prob = self.liveness_class[index],preds[index]
if is_show:
text = f"{name} , {pred_class}: {pred_prob*100:.4f}%"
cv2.rectangle(frame,(start_x,start_y),(end_x,end_y),
(0,0,255,2))
y = start_y - 10 if start_y - 10 > 10 else start_y + 10
cv2.putText(frame,text,(start_x,y),cv2.FONT_HERSHEY_SIMPLEX, 0.45, (0, 0, 255), 2)
return pred_class,pred_prob,frame
else:
return pred_class,pred_prob
if __name__ == "__main__":
model = Face_inference()
img = cv2.imread("R.jpg")
name,prob,res_frame = model.face_detect(img,is_show=True)
cv2.imshow("face",res_frame)
label,prob,res_frame = model.live_detect(img,name,is_show=True)
cv2.imshow("live",res_frame)
cv2.waitKey(0)