基于人脸动态特征的活体检测系统实现
创作时间:
作者:
@小白创作中心
基于人脸动态特征的活体检测系统实现
引用
CSDN
1.
https://blog.csdn.net/weixin_53742691/article/details/136610143
活体检测技术在人脸识别系统中扮演着至关重要的角色,它能够有效防止照片、视频等非活体介质的欺骗攻击。本文将介绍一种基于人脸动态特征(如眨眼、张嘴、摇头和点头)的活体检测方法,并提供完整的Python代码实现。
背景说明
在实际应用中,人脸识别系统常常面临以下挑战:
- 照片打卡问题:传统的打卡系统容易被照片欺骗
- 高昂的开发成本:现有的活体检测服务价格昂贵
- 低自主集成度:现有方案难以满足定制化需求
因此,开发一个成本低、可定制的活体检测系统具有重要意义。本文将介绍一种基于人脸动态特征的活体检测方法,通过分析视频流中的人脸动作来判断是否为活体。
技术原理
该系统主要通过分析视频流中的人脸动作来判断是否为活体。具体来说,系统会检测以下几种动作:
- 眨眼:通过计算眼睛的纵横比(EAR)来判断眼睛是否闭合
- 张嘴:通过计算嘴巴的纵横比(MAR)来判断嘴巴是否张开
- 摇头:通过分析鼻子到左右脸颊边界的距离变化来判断头部是否摇动
- 点头:通过分析眉毛到左右脸颊边界的距离变化来判断头部是否点头
代码实现
以下是完整的Python代码实现:
from scipy.spatial import distance as dist
from imutils.video import FileVideoStream
from imutils.video import VideoStream
from imutils import face_utils
import argparse
import imutils
import time
import dlib
import cv2
import numpy as np
def eye_aspect_ratio(eye):
A = dist.euclidean(eye[1], eye[5])
B = dist.euclidean(eye[2], eye[4])
C = dist.euclidean(eye[0], eye[3])
ear = (A + B) / (2.0 * C)
return ear
def mouth_aspect_ratio(mouth):
A = np.linalg.norm(mouth[2] - mouth[9])
B = np.linalg.norm(mouth[4] - mouth[7])
C = np.linalg.norm(mouth[0] - mouth[6])
mar = (A + B) / (2.0 * C)
return mar
def nose_jaw_distance(nose, jaw):
face_left1 = dist.euclidean(nose[0], jaw[0])
face_right1 = dist.euclidean(nose[0], jaw[16])
face_left2 = dist.euclidean(nose[3], jaw[2])
face_right2 = dist.euclidean(nose[3], jaw[14])
face_distance = (face_left1, face_right1, face_left2, face_right2)
return face_distance
def eyebrow_jaw_distance(leftEyebrow, jaw):
eyebrow_left = dist.euclidean(leftEyebrow[2], jaw[0])
eyebrow_right = dist.euclidean(leftEyebrow[2], jaw[16])
left_right = dist.euclidean(jaw[0], jaw[16])
eyebrow_distance = (eyebrow_left, eyebrow_right, left_right)
return eyebrow_distance
def Face_Recognize(file_path):
EYE_AR_THRESH = 0.27
EYE_AR_CONSEC_FRAMES = 2
MAR_THRESH = 0.5
COUNTER_EYE = 0
TOTAL_EYE = 0
COUNTER_MOUTH = 0
TOTAL_MOUTH = 0
distance_left = 0
distance_right = 0
TOTAL_FACE = 0
nod_flag = 0
TOTAL_NOD = 0
detector = dlib.get_frontal_face_detector()
predictor = dlib.shape_predictor("./static/shape_predictor_68_face_landmarks.dat")
(lStart, lEnd) = face_utils.FACIAL_LANDMARKS_IDXS["left_eye"]
(rStart, rEnd) = face_utils.FACIAL_LANDMARKS_IDXS["right_eye"]
(mStart, mEnd) = face_utils.FACIAL_LANDMARKS_IDXS["mouth"]
(nStart, nEnd) = face_utils.FACIAL_LANDMARKS_IDXS["nose"]
(jStart, jEnd) = face_utils.FACIAL_LANDMARKS_IDXS['jaw']
(Eyebrow_Start, Eyebrow_End) = face_utils.FACIAL_LANDMARKS_IDXS['left_eyebrow']
vs = FileVideoStream(file_path).start()
fileStream = True
time.sleep(1.0)
while True:
if fileStream and not vs.more():
break
frame = vs.read()
frame = imutils.resize(frame, width=600)
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
rects = detector(gray, 0)
for rect in rects:
shape = predictor(gray, rect)
shape = face_utils.shape_to_np(shape)
leftEye = shape[lStart:lEnd]
rightEye = shape[rStart:rEnd]
leftEAR = eye_aspect_ratio(leftEye)
rightEAR = eye_aspect_ratio(rightEye)
Mouth = shape[mStart:mEnd]
mouthMAR = mouth_aspect_ratio(Mouth)
nose = shape[nStart:nEnd]
jaw = shape[jStart:jEnd]
NOSE_JAW_Distance = nose_jaw_distance(nose, jaw)
leftEyebrow = shape[Eyebrow_Start:Eyebrow_End]
Eyebrow_JAW_Distance = eyebrow_jaw_distance(leftEyebrow, jaw)
ear = (leftEAR + rightEAR) / 2.0
mar = mouthMAR
face_left1 = NOSE_JAW_Distance[0]
face_right1 = NOSE_JAW_Distance[1]
face_left2 = NOSE_JAW_Distance[2]
face_right2 = NOSE_JAW_Distance[3]
eyebrow_left = Eyebrow_JAW_Distance[0]
eyebrow_right = Eyebrow_JAW_Distance[1]
left_right = Eyebrow_JAW_Distance[2]
if ear < EYE_AR_THRESH:
COUNTER_EYE += 1
else:
if COUNTER_EYE >= EYE_AR_CONSEC_FRAMES:
TOTAL_EYE += 1
COUNTER_EYE = 0
if mar > MAR_THRESH:
COUNTER_MOUTH += 1
else:
if COUNTER_MOUTH != 0:
TOTAL_MOUTH += 1
COUNTER_MOUTH = 0
if face_left1 >= face_right1 + 2 and face_left2 >= face_right2 + 2:
distance_left += 1
if face_right1 >= face_left1 + 2 and face_right2 >= face_left2 + 2:
distance_right += 1
if distance_left != 0 and distance_right != 0:
TOTAL_FACE += 1
distance_right = 0
distance_left = 0
if eyebrow_left + eyebrow_right <= left_right + 3:
nod_flag += 1
if nod_flag != 0 and eyebrow_left + eyebrow_right >= left_right + 3:
TOTAL_NOD += 1
nod_flag = 0
cv2.putText(frame, "Blinks: {}".format(TOTAL_EYE), (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 255), 2)
cv2.putText(frame, "Mouth is open: {}".format(TOTAL_MOUTH), (10, 60), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 255), 2)
cv2.putText(frame, "shake one's head: {}".format(TOTAL_FACE), (10, 90), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 255), 2)
cv2.putText(frame, "nod: {}".format(TOTAL_NOD), (10, 120), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 255), 2)
cv2.putText(frame, "Live detection: wink(5)", (300, 30), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 255), 2)
if TOTAL_EYE >= 5:
cv2.putText(frame, "open your mouth(3)", (300, 60), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 255), 2)
if TOTAL_MOUTH >= 3:
cv2.putText(frame, "shake your head(2)", (300, 90), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 255), 2)
if TOTAL_FACE >= 2:
cv2.putText(frame, "nod(2)", (300, 120), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 255), 2)
if TOTAL_NOD >= 2:
cv2.putText(frame, "Live detection: done", (300, 150), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 255), 2)
cv2.imshow("Frame", frame)
key = cv2.waitKey(1) & 0xFF
if key == ord("q"):
break
cv2.destroyAllWindows()
vs.stop()
if __name__ == '__main__':
Face_Recognize('path_to_your_video_file')
API接口
为了将上述功能封装成API服务,可以使用Flask框架。以下是API接口的实现代码:
import base64
from flask import Flask, request
import numpy as np
import cv2
import imutils
import dlib
from imutils import face_utils
import DynamicRecognition
app = Flask(__name__)
@app.route('/process_video', methods=['GET'])
def process_video():
file_path = request.args.get('file_path')
DynamicRecognition.Face_Recognize(file_path)
return {"result": "Processed successfully"}
if __name__ == '__main__':
app.run(debug=True)
效果测试
以下是系统运行效果的示例截图:
通过上述方法,可以实现基于人脸动态特征的活体检测系统。虽然目前的实现方式是通过视频文件进行处理,但未来可以考虑采用实时视频流传输的方式,以提高系统的实时性和交互性。
热门推荐
冬至汤圆制作完全指南:传统工艺与创新做法详解
D9双星系统现身银河系中心,挑战极端环境恒星形成理论
中国四大名楼:黄鹤、鹳雀、滕王阁、岳阳,千年来诗文传颂、屡毁屡建
磨砺利剑 守护正义——记金昌中院司法警察警用装备训练提升周
家具行业的三包规定是指哪三包
宋庆龄学校举办融合游园会,促进普特儿童互动交流
“绿书签”赋能全民阅读,建设高质量书香福田
从结节到胸腔积液:肺隐球菌病的CT影像特征
哪种解冻方法让你的肉馅更健康?
12日广州气温创2025年以来新低,新冷空气已安排上了
内蒙古“达达线”入选2024年最美自驾精品路
广州南站暑运出行指南:安检3秒通关,多种换乘方案
社交心理学教你高效表达,职场沟通不再难
慢性胃炎患者的饮食避坑指南
穴位养生 | 按揉鱼际穴,远离鼠标手
氨基葡萄糖火爆保健品市场,银发族的新宠儿
冬至包饺子,首选这三种当季海鲜食材
诺贝尔文学奖的标准:故事文学造诣的评价指南
《魔兽世界》20年:技术革新与怀旧服带来的双重魅力与挑战
乙肝防治面临挑战:8000万感染者仅15%接受治疗,专家呼吁加强筛查
植物大战僵尸3.0.1更新:冒险模式大升级,新增多类植物僵尸
肌酐异常,警惕慢性肾病来袭
小柴胡汤:中医养生神器,告别口苦烦恼
新型药物缓解困扰数亿女性的问题!JAMA:治疗更年期症状,还改善这2大指标
普洱茶香气的秘密:四大要素塑造独特韵味
专家提醒:孕妇慎用贞芪扶正颗粒
路易波士茶:来自南非的健康茶饮新选择
更年期,常吃这几种食物
辽宁舰入列12周年:从改装到成熟,中国航母力量的崛起
沪深300ETF:新手投资者的稳健投资利器