You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

98 lines
3.5 KiB

import cv2
from arcsoft.engine import *
from .exception import FaceNotFoundException, FaceMoreFoundException, ArcSoftCallException, NonLivingException
from conf import setting
class FaceCameraEngine:
def __init__(self):
self.app_id = bytes(setting.ARCSOFT_APP_ID, 'utf-8')
self.sdk_key = bytes(setting.ARCSOFT_SDK_KEY, 'utf-8')
def __enter__(self):
face_engine = ArcFace()
face_engine.ASFInitEngine(ASF_DETECT_MODE_IMAGE, ASF_OP_0_ONLY, 30, 5, ASF_FACE_DETECT | ASF_FACERECOGNITION | ASF_LIVENESS)
self.face_engine = face_engine
return self
# 虹软库激活
def activation(self) -> bool:
ack = ASFOnlineActivation(self.app_id, self.sdk_key)
return (MOK == ack or MERR_ASF_ALREADY_ACTIVATED == ack)
# 查找相似特征人员
def match(self, frame, features: dict) -> str:
frame = self.do_resize(frame)
ack, detect_faces = self.face_engine.ASFDetectFaces(frame)
if MOK != ack:
raise ArcSoftCallException()
if detect_faces.faceNum == 0:
raise FaceNotFoundException()
if detect_faces.faceNum > 1:
raise FaceMoreFoundException()
ack = self.face_engine.ASFProcess(frame, detect_faces, ASF_LIVENESS)
if MOK != ack:
raise ArcSoftCallException()
ack, liveness = self.face_engine.ASFGetLivenessScore()
if MOK != ack:
raise ArcSoftCallException()
# TODO: 是否活体(还需进一步测试)
if liveness.isLive[0] != 1:
raise NonLivingException()
# 特征值
single_face_info = ASF_SingleFaceInfo()
single_face_info.faceRect = detect_faces.faceRect[0]
single_face_info.faceOrient = detect_faces.faceOrient[0]
ack, feature = self.face_engine.ASFFaceFeatureExtract(frame, single_face_info)
if MOK != ack:
raise ArcSoftCallException()
for (key, value) in features.items():
ack, score = self.face_engine.ASFFaceFeatureCompare(feature, value)
if MOK != ack:
continue
if score >= setting.FACE_RECOGNITION_THRESHOLD:
return key
# 捕获图像人脸特征值
def capture(self, frame) -> List[bytes]:
frame = self.do_resize(frame)
ack, detect_faces = self.face_engine.ASFDetectFaces(frame)
if MOK != ack:
raise ArcSoftCallException()
data = []
for i in range(0, detect_faces.faceNum):
single_face_info = ASF_SingleFaceInfo()
single_face_info.faceRect = detect_faces.faceRect[i]
single_face_info.faceOrient = detect_faces.faceOrient[i]
ack, feature = self.face_engine.ASFFaceFeatureExtract(frame, single_face_info)
if MOK == ack:
data.append(feature.get_feature_bytes())
return data if len(data) > 0 else None
# 二进制转特征值
@staticmethod
def b2f(bin: bytes) -> ASF_FaceFeature:
face_feature = ASF_FaceFeature()
face_feature.featureSize = bin.__len__()
face_feature.feature = lib_func.malloc(face_feature.featureSize)
lib_func.memcpy(face_feature.feature, bin, face_feature.featureSize)
return face_feature
def __exit__(self, type, value, trace):
self.face_engine.ASFUninitEngine()
# 处理图片宽域
def do_resize(self, frame):
sp = frame.shape
return cv2.resize(frame, (sp[1] // 4 * 4, sp[0]))