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]))