File size: 3,292 Bytes
59234d3
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
import os
import sys
import numpy as np
import ctypes, ctypes.util
from enum import Enum
from ctypes import *
from numpy.ctypeslib import ndpointer

def print_log(fmt): print("[LOG] \033[98m{}\033[00m" .format(fmt))
def print_info(fmt): print("[INFO] \033[92m{}\033[00m" .format(fmt))
def print_error(fmt): print("[ERR] \033[91m{}\033[00m" .format(fmt)) 
def print_warning(fmt): print("[WARNING] \033[93m{}\033[00m" .format(fmt))

class ENGINE_CODE(Enum):
    E_NO_FACE = 0
    E_ACTIVATION_ERROR = -1
    E_ENGINE_INIT_ERROR = -2
    
class LIVENESS_CODE(Enum):
    L_TOO_SMALL_FACE = -100
    L_BORDERLINE_FACE = -200
    L_TOO_TURNED_FACE = -300
    L_COVERED_FACE = -400
    L_MULTIPLE_FACE = -500
    L_DEEP_FAKE = -600

lib_path = os.path.abspath(os.path.dirname(__file__)) + '/libliveness_v7.so'
lib = cdll.LoadLibrary(lib_path)

get_version = lib.ttv_version
get_version.argtypes = []
get_version.restype = ctypes.c_char_p

get_deviceid = lib.ttv_get_hwid
get_deviceid.argtypes = []
get_deviceid.restype = ctypes.c_char_p

init_sdk = lib.ttv_init
init_sdk.argtypes = [ctypes.c_char_p, ctypes.c_char_p]
init_sdk.restype = ctypes.c_int32

init_sdk_offline = lib.ttv_init_offline
init_sdk_offline.argtypes = [ctypes.c_char_p, ctypes.c_char_p]
init_sdk_offline.restype = ctypes.c_int32


detect_face_rgb = lib.ttv_detect_face
detect_face_rgb.argtypes = [ndpointer(ctypes.c_ubyte, flags='C_CONTIGUOUS'), ctypes.c_int32, ctypes.c_int32, ndpointer(ctypes.c_int32, flags='C_CONTIGUOUS'), ndpointer(ctypes.c_double, flags='C_CONTIGUOUS'), ndpointer(ctypes.c_double, flags='C_CONTIGUOUS')]
detect_face_rgb.restype = ctypes.c_int32

DEFAULT_THRESHOLD = 0
def check_liveness(image_mat, spoof_threshold = DEFAULT_THRESHOLD):
    result = ""
    score = 0

    if image_mat is None:
        result = "Failed to open image"
        return result, None, None, None
    
    face_rect = np.zeros([4], dtype=np.int32)
    liveness_score = np.zeros([1], dtype=np.double)
    angles = np.zeros([3], dtype=np.double)

    width = image_mat.shape[1]
    height = image_mat.shape[0]

    ret = detect_face_rgb(image_mat, width, height, face_rect, liveness_score, angles)

    if ret <= 0:
        if ret == ENGINE_CODE.E_ACTIVATION_ERROR.value:
            result = "ACTIVATION ERROR"
        elif ret == ENGINE_CODE.E_ENGINE_INIT_ERROR.value:
            result = "ENGINE INIT ERROR"
        elif ret == ENGINE_CODE.E_NO_FACE.value:
            result = "NO FACE"
        return result, None, None, None
    
    score = liveness_score[0]
    if score == LIVENESS_CODE.L_TOO_SMALL_FACE.value:
        result = "TOO SMALL FACE"
    elif score == LIVENESS_CODE.L_BORDERLINE_FACE.value:
        result = "FACE CUT OFF"
    elif score == LIVENESS_CODE.L_TOO_TURNED_FACE.value:
        result = "TOO TURNED FACE"
    elif score == LIVENESS_CODE.L_COVERED_FACE.value:
        result = "COVERED FACE"
    elif score == LIVENESS_CODE.L_MULTIPLE_FACE.value:
        result = "MULTIPLE FACES"
    elif score == LIVENESS_CODE.L_DEEP_FAKE.value:
        result = "DEEP FAKE DETECTED"
    elif score > spoof_threshold:
        result = "REAL"
    else:
        result = "SPOOF"

    return result, face_rect, score, angles