Repository navigation
Expand file tree
/
Copy pathsdk.py
More file actions
137 lines (107 loc) · 3.52 KB
/
Copy pathsdk.py
File metadata and controls
137 lines (107 loc) · 3.52 KB
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
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
"""ctypes bindings to FaceLivenessSDK.dll (Face Liveness, Windows).
Native libs live in lib/cpu/.
"""
from __future__ import annotations
import base64
import ctypes
import io
import json
import os
import sys
from pathlib import Path
ROOT = Path(__file__).resolve().parent
LIB = ROOT / "lib" / "cpu"
DLL = LIB / "FaceLivenessSDK.dll"
os.chdir(ROOT)
os.environ["PATH"] = str(LIB) + os.pathsep + os.environ.get("PATH", "")
if hasattr(os, "add_dll_directory"):
os.add_dll_directory(str(LIB))
if not DLL.is_file():
print(
f"ERROR: missing {DLL}\n"
"Download the Windows runtime into .\\lib\\cpu\\.",
file=sys.stderr,
)
raise SystemExit(1)
_dll = ctypes.WinDLL(str(DLL))
_dll.FaceSDK_initSDK.restype = ctypes.c_int
_dll.FaceSDK_initSDK.argtypes = []
_dll.FaceSDK_activate.restype = ctypes.c_int
_dll.FaceSDK_activate.argtypes = [ctypes.c_char_p]
_dll.FaceSDK_getMachineCode.restype = ctypes.c_int
_dll.FaceSDK_getMachineCode.argtypes = [ctypes.c_char_p]
_dll.FaceSDK_liveness_all.restype = ctypes.c_int
_dll.FaceSDK_liveness_all.argtypes = [ctypes.c_char_p, ctypes.c_int, ctypes.c_char_p]
def _opt_sym(name, restype, argtypes):
fn = getattr(_dll, name, None)
if fn is None:
return None
fn.restype = restype
fn.argtypes = argtypes
return fn
_get_license_status = _opt_sym(
"FaceSDK_getLicenseStatus", ctypes.c_int, [ctypes.c_char_p]
)
_MC_BUF = 768
_STATUS_BUF = 512
_OUT = 2 * 1024 * 1024
_MAX_IMG = 8 * 1024 * 1024
def _b(v) -> bytes:
if isinstance(v, bytes):
return v
return str(v).encode("utf-8")
def _jpeg_bytes(image_b64: str) -> bytes:
text = image_b64.strip()
if text.startswith("data:") and "base64," in text:
text = text.split("base64,", 1)[1]
data = base64.b64decode(text, validate=False)
if len(data) <= _MAX_IMG and data[:2] == b"\xff\xd8":
return data
from PIL import Image
img = Image.open(io.BytesIO(data))
img.load()
if img.mode not in ("RGB", "L"):
img = img.convert("RGB")
buf = io.BytesIO()
img.save(buf, format="JPEG", quality=90)
out = buf.getvalue()
while len(out) > _MAX_IMG and img.width > 32:
img = img.resize((max(1, int(img.width * 0.75)), max(1, int(img.height * 0.75))))
buf = io.BytesIO()
img.save(buf, format="JPEG", quality=80)
out = buf.getvalue()
return out
def get_machine_code() -> str:
buf = ctypes.create_string_buffer(_MC_BUF)
_dll.FaceSDK_getMachineCode(buf)
return buf.value.decode("utf-8", errors="replace")
def get_license_status() -> dict:
fallback = {
"licensed": False,
"level": -1,
"levelName": "None",
"recognition": False,
"liveness": False,
"label": "Not licensed",
}
if _get_license_status is None:
return fallback
buf = ctypes.create_string_buffer(_STATUS_BUF)
if int(_get_license_status(buf)) != 0:
return fallback
try:
data = json.loads(buf.value.decode("utf-8", errors="replace") or "{}")
return data if isinstance(data, dict) else fallback
except Exception: # noqa: BLE001
return fallback
def activate(license_path: str) -> int:
return int(_dll.FaceSDK_activate(_b(license_path)))
def init_sdk() -> int:
return int(_dll.FaceSDK_initSDK())
def backend() -> str:
return "cpu"
def liveness(image: str) -> str:
jpeg = _jpeg_bytes(image)
out = ctypes.create_string_buffer(_OUT)
_dll.FaceSDK_liveness_all(jpeg, len(jpeg), out)
return out.value.decode("utf-8", errors="replace")