Skip to content

Commit

Permalink
Update
Browse files Browse the repository at this point in the history
  • Loading branch information
zhu-j-faceonlive committed Jul 7, 2023
1 parent 79e8000 commit 6e702fa
Show file tree
Hide file tree
Showing 11 changed files with 130 additions and 211 deletions.
262 changes: 80 additions & 182 deletions app.py
Original file line number Diff line number Diff line change
@@ -1,217 +1,115 @@
import sys
sys.path.append('.')

import cv2
import numpy as np
from flask import Flask, request, jsonify
from time import gmtime, strftime
import logging
import uuid
from flask_cors import CORS
import os
import base64

from facewrapper.facewrapper import InitEngine
from facewrapper.facewrapper import GetLiveness
from facewrapper.facewrapper import ProcessAll
from facewrapper.facewrapper import CompareFace

import json
import cv2
import numpy as np

CUSTOMER_TOKENS = [
####### 07.05 #######
]

from facewrapper.facewrapper import ttv_version
from facewrapper.facewrapper import ttv_get_hwid
from facewrapper.facewrapper import ttv_init
from facewrapper.facewrapper import ttv_init_offline
from facewrapper.facewrapper import ttv_detect_face

app = Flask(__name__)
CORS(app)
app = Flask(__name__)

licensePath = os.path.abspath(os.path.dirname(__file__)) + '/facewrapper/license.txt'
InitEngine(licensePath.encode('utf-8'))
app.config['SITE'] = "http://0.0.0.0:8000/"
app.config['DEBUG'] = False

@app.route('/face/liveness', methods=['POST'])
def detect_livness():
print('>>>>>>>>>>>>>/face/liveness', strftime("%Y-%m-%d %H:%M:%S", gmtime()), '\t\t\t', request.remote_addr)
app.logger.info(request.remote_addr)
licenseKey = "XXXXX-XXXXX-XXXXX-XXXXX"
licensePath = "license.txt"
modelFolder = os.path.abspath(os.path.dirname(__file__)) + '/facewrapper/dict'

file = request.files['image']
version = ttv_version()
print("version: ", version.decode('utf-8'))

image = cv2.imdecode(np.fromstring(file.read(), np.uint8), cv2.IMREAD_COLOR)
file_name = uuid.uuid4().hex[:6]
save_path = 'dump2/' + file_name + '.png'
cv2.imwrite(save_path, image)

bbox = np.zeros([4], dtype=np.int32)
live_score = GetLiveness(image, image.shape[1], image.shape[0], bbox)

if live_score == 1:
result = "Genuine"
elif live_score == -102:
result = "Face not detected"
elif live_score == -103:
result = "Liveness failed"
elif live_score == 0:
result = "Spoof"
elif live_score == -3:
result = "Face is too small"
elif live_score == -4:
result = "Face is too large"
else:
result = "Error"
status = "ok"
ret = ttv_init(modelFolder.encode('utf-8'), licenseKey.encode('utf-8'))
if ret != 0:
print(f"online init failed: {ret}");

response = jsonify({"status": status, "data": {"result": result, "box": {"x": int(bbox[0]), "y": int(bbox[1]), "w": int(bbox[2] - bbox[0] + 1), "h" : int(bbox[3] - bbox[1] + 1)}, "score": live_score}})
hwid = ttv_get_hwid()
print("hwid: ", hwid.decode('utf-8'))

response.status_code = 200
response.headers["Content-Type"] = "application/json; charset=utf-8"
return response
ret = ttv_init_offline(modelFolder.encode('utf-8'), licensePath.encode('utf-8'))
if ret != 0:
print(f"offline init failed: {ret}")
exit(-1)
else:
print(f"offline init ok")

@app.route('/face/attribute', methods=['POST'])
def processAll():
print('>>>>>>>>>>>>>/face/attribute', strftime("%Y-%m-%d %H:%M:%S", gmtime()), '\t\t\t', request.remote_addr)
app.logger.info(request.remote_addr)
else:
print(f"online init ok")

@app.route('/api/liveness', methods=['POST'])
def check_liveness():
file = request.files['image']

image = cv2.imdecode(np.fromstring(file.read(), np.uint8), cv2.IMREAD_COLOR)
file_name = uuid.uuid4().hex[:6]
save_path = 'dump2/' + file_name + '.png'
cv2.imwrite(save_path, image)

bbox = np.zeros([4], dtype=np.int32)
attribute = np.zeros([4], dtype=np.int32)
angles = np.zeros([3], dtype=np.float)
liveness = np.zeros([1], dtype=np.int32)
age = np.zeros([1], dtype=np.int32)
gender = np.zeros([1], dtype=np.int32)
mask = np.zeros([1], dtype=np.int32)
feature = np.zeros([4096], dtype=np.uint8)
featureSize = np.zeros([1], dtype=np.int32)
ret = ProcessAll(image, image.shape[1], image.shape[0], bbox, attribute, angles, liveness, age, gender, mask, feature, featureSize, 0)

print("facebox: ", bbox[0], " ", bbox[1], " ", bbox[2], " ", bbox[3])
print(f"wearGlasses: {attribute[0]}, leftEyeOpen: {attribute[1]}, rightEyeOpen: {attribute[2]}, mouthClose: {attribute[3]}")
print(f"roll: {angles[0]} yaw: {angles[1]}, pitch: {angles[2]}")
print(f"liveness: {liveness[0]}")
print(f"age: {age[0]}")
print(f"gender: {gender[0]}")
print(f"mask: {mask[0]}")
print(f"feature size: {featureSize[0]}")

if ret == 0:
result = "Face detected"
elif ret == -1:
result = "Engine not inited"

faceRect = np.zeros([4], dtype=np.int32)
livenessScore = np.zeros([1], dtype=np.double)
angles = np.zeros([3], dtype=np.double)
ret = ttv_detect_face(image, image.shape[1], image.shape[0], faceRect, livenessScore, angles)
if ret == -1:
result = "license error!"
elif ret == -2:
result = "No face detected"
result = "init error!"
elif ret == 0:
result = "no face detected!"
elif ret > 1:
result = "multiple face detected!"
elif faceRect[0] < 0 or faceRect[1] < 0 or faceRect[2] >= image.shape[1] or faceRect[2] >= image.shape[0]:
result = "faace is in boundary!"
elif livenessScore[0] > 0:
result = "genuine"
else:
result = "Error"
result = "spoof"

status = "ok"

response = jsonify({"status": status, "data": {"result": result, "box": {"x": int(bbox[0]), "y": int(bbox[1]), "w": int(bbox[2] - bbox[0] + 1), "h" : int(bbox[3] - bbox[1] + 1)},
"attr": {"wear_glasses": int(attribute[0]), "left_eye_open": int(attribute[1]), "right_eye_open": int(attribute[2]), "mouth_close": int(attribute[3])},
"angles": {"roll": float(angles[0]), "yaw": float(angles[1]), "pitch": float(angles[2])},
"liveness": int(liveness[0]),
"age": int(age[0]),
"gender": int(gender[0]),
"mask": int(mask[0])
}})
response = jsonify({"status": status, "data": {"result": result, "face_rect": {"x": int(faceRect[0]), "y": int(faceRect[1]), "w": int(faceRect[2] - faceRect[0] + 1), "h" : int(faceRect[3] - faceRect[1] + 1)}, "liveness_score": livenessScore[0],
"angles": {"yaw": angles[0], "roll": angles[1], "pitch": angles[2]}}})

response.status_code = 200
response.headers["Content-Type"] = "application/json; charset=utf-8"
return response

@app.route('/face/compare', methods=['POST'])
def compareFace():
print('>>>>>>>>>>>>>/face/compare', strftime("%Y-%m-%d %H:%M:%S", gmtime()), '\t\t\t', request.remote_addr)
app.logger.info(request.remote_addr)

file1 = request.files['image1']
image1 = cv2.imdecode(np.fromstring(file1.read(), np.uint8), cv2.IMREAD_COLOR)

file2 = request.files['image2']
image2 = cv2.imdecode(np.fromstring(file2.read(), np.uint8), cv2.IMREAD_COLOR)

bbox1 = np.zeros([4], dtype=np.int32)
attribute1 = np.zeros([4], dtype=np.int32)
angles1 = np.zeros([3], dtype=np.float)
liveness1 = np.zeros([1], dtype=np.int32)
age1 = np.zeros([1], dtype=np.int32)
gender1 = np.zeros([1], dtype=np.int32)
mask1 = np.zeros([1], dtype=np.int32)
feature1 = np.zeros([4096], dtype=np.uint8)
featureSize1 = np.zeros([1], dtype=np.int32)
ret = ProcessAll(image1, image1.shape[1], image1.shape[0], bbox1, attribute1, angles1, liveness1, age1, gender1, mask1, feature1, featureSize1, 0)

print('image1 results>>>>>>>>')
print("facebox: ", bbox1[0], " ", bbox1[1], " ", bbox1[2], " ", bbox1[3])
print(f"wearGlasses: {attribute1[0]}, leftEyeOpen: {attribute1[1]}, rightEyeOpen: {attribute1[2]}, mouthClose: {attribute1[3]}")
print(f"roll: {angles1[0]} yaw: {angles1[1]}, pitch: {angles1[2]}")
print(f"liveness: {liveness1[0]}")
print(f"age: {age1[0]}")
print(f"gender: {gender1[0]}")
print(f"mask: {mask1[0]}")
print(f"feature size: {featureSize1[0]}")
print("<<<<<<<<<<<<<<")

if ret != 0:
if ret == -1:
result = "Engine not inited"
elif ret == -2:
result = "No face detected in image1"
else:
result = "Error in image1"

response = jsonify({"status": status, "data": {"result": result}})
response.status_code = 200
response.headers["Content-Type"] = "application/json; charset=utf-8"
return response

bbox2 = np.zeros([4], dtype=np.int32)
attribute2 = np.zeros([4], dtype=np.int32)
angles2 = np.zeros([3], dtype=np.float)
liveness2 = np.zeros([1], dtype=np.int32)
age2 = np.zeros([1], dtype=np.int32)
gender2 = np.zeros([1], dtype=np.int32)
mask2 = np.zeros([1], dtype=np.int32)
feature2 = np.zeros([4096], dtype=np.uint8)
featureSize2 = np.zeros([1], dtype=np.int32)
ret = ProcessAll(image2, image2.shape[1], image2.shape[0], bbox2, attribute2, angles2, liveness2, age2, gender2, mask2, feature2, featureSize2, 1)

print('image2 results>>>>>>>>')
print("facebox: ", bbox2[0], " ", bbox2[1], " ", bbox2[2], " ", bbox2[3])
print(f"wearGlasses: {attribute2[0]}, leftEyeOpen: {attribute2[1]}, rightEyeOpen: {attribute2[2]}, mouthClose: {attribute2[3]}")
print(f"roll: {angles2[0]} yaw: {angles2[1]}, pitch: {angles2[2]}")
print(f"liveness: {liveness2[0]}")
print(f"age: {age2[0]}")
print(f"gender: {gender2[0]}")
print(f"mask: {mask2[0]}")
print(f"feature size: {featureSize2[0]}")
print("<<<<<<<<<<<<<<")

if ret != 0:
if ret == -1:
result = "Engine not inited"
elif ret == -2:
result = "No face detected in image2"
else:
result = "Error in image2"

response = jsonify({"status": status, "data": {"result": result}})
response.status_code = 200
response.headers["Content-Type"] = "application/json; charset=utf-8"
return response

confidence = CompareFace(feature1, featureSize1[0], feature2, featureSize2[0])
if confidence > 0.82:
result = "Same"
@app.route('/api/liveness_base64', methods=['POST'])
def check_liveness_base64():
content = request.get_json()
imageBase64 = content['image']
image = cv2.imdecode(np.frombuffer(base64.b64decode(imageBase64), dtype=np.uint8), cv2.IMREAD_COLOR)

faceRect = np.zeros([4], dtype=np.int32)
livenessScore = np.zeros([1], dtype=np.double)
angles = np.zeros([3], dtype=np.double)
ret = ttv_detect_face(image, image.shape[1], image.shape[0], faceRect, livenessScore, angles)
if ret == -1:
result = "license error!"
elif ret == -2:
result = "init error!"
elif ret == 0:
result = "no face detected!"
elif ret > 1:
result = "multiple face detected!"
elif faceRect[0] < 0 or faceRect[1] < 0 or faceRect[2] >= image.shape[1] or faceRect[2] >= image.shape[0]:
result = "faace is in boundary!"
elif livenessScore[0] > 0:
result = "genuine"
else:
result = "Different"
result = "spoof"

status = "ok"

response = jsonify({"status": status, "data": {"result": result, "similarity": float(confidence)}})
response = jsonify({"status": status, "data": {"result": result, "face_rect": {"x": int(faceRect[0]), "y": int(faceRect[1]), "w": int(faceRect[2] - faceRect[0] + 1), "h" : int(faceRect[3] - faceRect[1] + 1)}, "liveness_score": livenessScore[0],
"angles": {"yaw": angles[0], "roll": angles[1], "pitch": angles[2]}}})

response.status_code = 200
response.headers["Content-Type"] = "application/json; charset=utf-8"
return response


if __name__ == '__main__':
port = int(os.environ.get("PORT", 8000))
app.run(host='0.0.0.0', port=port)
1 change: 0 additions & 1 deletion facewrapper/README.md

This file was deleted.

38 changes: 18 additions & 20 deletions facewrapper/facewrapper.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,31 +3,29 @@
from numpy.ctypeslib import ndpointer
import sys
import os
sys.path.append('/opt/intel/openvino_2022/runtime/lib/intel64')

dll_path = os.path.abspath(os.path.dirname(__file__)) + '/libttvrecog.so'
face_engine = cdll.LoadLibrary(dll_path)
lib_path = os.path.abspath(os.path.dirname(__file__)) + '/libs/libttvfaceengine7.so'
liveness_engine = cdll.LoadLibrary(lib_path)

dll_path = os.path.abspath(os.path.dirname(__file__)) + '/libttvsdk.so'
face_engine = cdll.LoadLibrary(dll_path)
ttv_version = liveness_engine.ttv_version
ttv_version.argtypes = []
ttv_version.restype = ctypes.c_char_p

dll_path = os.path.abspath(os.path.dirname(__file__)) + '/libttvfaceengine.so'
face_engine = cdll.LoadLibrary(dll_path)
ttv_get_hwid = liveness_engine.ttv_get_hwid
ttv_get_hwid.argtypes = []
ttv_get_hwid.restype = ctypes.c_char_p

dll_path = os.path.abspath(os.path.dirname(__file__)) + '/libfacewrapper.so'
face_engine = cdll.LoadLibrary(dll_path)
ttv_init = liveness_engine.ttv_init
ttv_init.argtypes = [ctypes.c_char_p, ctypes.c_char_p]
ttv_init.restype = ctypes.c_int32

InitEngine = face_engine.InitEngine
InitEngine.argtypes = [ctypes.c_char_p]
InitEngine.restype = ctypes.c_int32
ttv_init_offline = liveness_engine.ttv_init_offline
ttv_init_offline.argtypes = [ctypes.c_char_p, ctypes.c_char_p]
ttv_init_offline.restype = ctypes.c_int32

GetLiveness = face_engine.GetLiveness
GetLiveness.argtypes = [ndpointer(ctypes.c_ubyte, flags='C_CONTIGUOUS'), ctypes.c_int32, ctypes.c_int32, ndpointer(ctypes.c_int32, flags='C_CONTIGUOUS')]
GetLiveness.restype = ctypes.c_int32

ProcessAll = face_engine.ProcessAll
ProcessAll.argtypes = [ndpointer(ctypes.c_ubyte, flags='C_CONTIGUOUS'), ctypes.c_int32, ctypes.c_int32, ndpointer(ctypes.c_int32, flags='C_CONTIGUOUS'), ndpointer(ctypes.c_int32, flags='C_CONTIGUOUS'), ndpointer(ctypes.c_double, flags='C_CONTIGUOUS'), ndpointer(ctypes.c_int32, flags='C_CONTIGUOUS'), ndpointer(ctypes.c_int32, flags='C_CONTIGUOUS'), ndpointer(ctypes.c_int32, flags='C_CONTIGUOUS'), ndpointer(ctypes.c_int32, flags='C_CONTIGUOUS'), ndpointer(ctypes.c_ubyte, flags='C_CONTIGUOUS'), ndpointer(ctypes.c_int32, flags='C_CONTIGUOUS'), ctypes.c_int32]
ProcessAll.restype = ctypes.c_int32
ttv_detect_face = liveness_engine.ttv_detect_face
ttv_detect_face.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')]
ttv_detect_face.restype = ctypes.c_int32

CompareFace = face_engine.CompareFace
CompareFace.argtypes = [ndpointer(ctypes.c_ubyte, flags='C_CONTIGUOUS'), ctypes.c_int32, ndpointer(ctypes.c_ubyte, flags='C_CONTIGUOUS'), ctypes.c_int32]
CompareFace.restype = ctypes.c_double
Binary file added facewrapper/libs/libimutils.so
Binary file not shown.
Binary file added facewrapper/libs/libimutils.so_for_ubuntu22
Binary file not shown.
Binary file added facewrapper/libs/libttvfaceengine7.so
Binary file not shown.
29 changes: 29 additions & 0 deletions install_dependency.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
#!/bin/bash

wget --load-cookies /tmp/cookies.txt "https://docs.google.com/uc?export=download&confirm=$(wget --quiet --save-cookies /tmp/cookies.txt --keep-session-cookies --no-check-certificate 'https://docs.google.com/uc?export=download&id=15ilPQKc3SM0bEQHrJfovO97ejhftW7zr' -O- | sed -rn 's/.*confirm=([0-9A-Za-z_]+).*/\1\n/p')&id=15ilPQKc3SM0bEQHrJfovO97ejhftW7zr" -O openvino.tar.xz && rm -rf /tmp/cookies.txt

tar -xvxf openvino.tar.xz
sudo cp ./openvino/* /usr/lib -rf

wget --load-cookies /tmp/cookies.txt "https://docs.google.com/uc?export=download&confirm=$(wget --quiet --save-cookies /tmp/cookies.txt --keep-session-cookies --no-check-certificate 'https://docs.google.com/uc?export=download&id=1td4iJU1O4NyIxAD5och_pyg6DfBKiR0V' -O- | sed -rn 's/.*confirm=([0-9A-Za-z_]+).*/\1\n/p')&id=1td4iJU1O4NyIxAD5och_pyg6DfBKiR0V" -O dict.zip && rm -rf /tmp/cookies.txt

unzip dict.zip
mv ./dict ./facewrapper

lsb_result=$(lsb_release -a)

if [[ "$lsb_result" == *"Ubuntu 22.04"* ]]; then
#echo "Current OS: Ubuntu 22.04"
sudo cp ./facewrapper/libs/libimutils.so_for_ubuntu22 /usr/lib/libimutils.so
elif [[ "$lsb_result" == *"Ubuntu 20.04"* ]]; then
#echo "Current OS: Ubuntu 20.04"
sudo cp ./facewrapper/libs/libimutils.so /usr/lib
else
echo "***No supported OS, Please try on Ubuntu 20.04 or later***"
exit
fi

sudo apt-get update && sudo apt-get install -y python3-pip python3-opencv libcurl4-openssl-dev libssl-dev libtbb-dev

pip3 install -r requirements.txt
echo '*** Installed dependency, Please try python3 app.py ***'
Empty file added license.txt
Empty file.
3 changes: 3 additions & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
opencv-python
flask
flask-cors
5 changes: 0 additions & 5 deletions run.sh

This file was deleted.

3 changes: 0 additions & 3 deletions waitress_server.py

This file was deleted.

0 comments on commit 6e702fa

Please sign in to comment.