first commit

This commit is contained in:
2024-04-13 22:06:43 +08:00
commit 1d243e5f4d
13 changed files with 2009 additions and 0 deletions
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 330 KiB

+21
View File
@@ -0,0 +1,21 @@
# 人脸检测识别&&活体识别
## 1. 运行环境
`conda create -n py39 python=3.9`
`conda activate py39`
运行所需依赖库
`pip install tensorflow==2.11.0 scipy scikit-learn==1.0.2 numpy imutils opencv-python gradio`
## 2. 文件
+ **models:** 包含各模型权重文件
+ **pickles:** 包含不同模型对应类别编码以及人脸识别中SVM分类器模型
+ **infer.py** 包含封装后的推理模型,包括人脸识别和活体识别的推理
+ **app.py** 包含gradio创建的web服务
## 3. 运行
`python main.py`
Binary file not shown.
Binary file not shown.
+35
View File
@@ -0,0 +1,35 @@
import cv2
import numpy as np
import gradio as gr
from infer import Face_inference
# 当设置置信度阈值较大时,人脸检测返回值为空,此时直接返回原图
def inference(image,thresh,model_type):
global name
if image is None:
yield image
if model_type == "人脸识别":
if m_model.face_detect(image,thresh,is_show=True) is None:
yield image
else:
name,prob,res_frame = m_model.face_detect(image,thresh,is_show=True)
yield res_frame
else:
if m_model.live_detect(image,name,thresh,is_show=True) is None:
yield image
else:
label,prob,res_frame = m_model.live_detect(image,name,thresh,is_show=True)
yield res_frame
model_name = gr.Radio(["人脸识别","活体检测"],value="人脸识别",label="Model",info="选择需要的模型")
threshold = gr.Slider(0.001,1,value=0.1,label="threshold",info="设置置信度阈值")
inputs_webcam = gr.Image(sources=["webcam"],streaming=True)
outputs_image = gr.Image(type="numpy",label="结果图片")
if __name__ == "__main__":
m_model = Face_inference()
name = ""
demo = gr.Interface(inference,inputs=[inputs_webcam,threshold,model_name],outputs=outputs_image,live=True,title="检测")
demo.queue().launch(max_threads=8)
+163
View File
@@ -0,0 +1,163 @@
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)
File diff suppressed because it is too large Load Diff
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.