mirror of
https://github.com/Yshelgi/face_web.git
synced 2026-05-25 16:00:28 +00:00
163 lines
6.0 KiB
Python
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) |