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
98 lines
3.5 KiB
4 months ago
|
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]))
|