Spaces:
Running
Running
justin2341
commited on
Commit
•
c88be80
1
Parent(s):
87a7370
Upload 25 files
Browse files- .gitattributes +1 -0
- Dockerfile +21 -0
- app.py +223 -0
- data/detect.bin +3 -0
- data/eye.bin +3 -0
- data/landmark.bin +3 -0
- data/templates.bin +3 -0
- demo.py +141 -0
- face_examples/1.jpg +0 -0
- face_examples/10.jpg +0 -0
- face_examples/2.jpg +0 -0
- face_examples/3.jpg +0 -0
- face_examples/4.jpg +0 -0
- face_examples/5.jpg +0 -0
- face_examples/6.jpg +0 -0
- face_examples/7.jpg +0 -0
- face_examples/8.jpg +0 -0
- face_examples/9.jpg +0 -0
- facebox.py +11 -0
- facesdk.py +32 -0
- libfacesdk2.so +3 -0
- libimutils.so +0 -0
- libimutils.so_for_ubuntu22 +0 -0
- license.txt +5 -0
- requirements.txt +6 -0
- run.sh +5 -0
.gitattributes
CHANGED
@@ -33,3 +33,4 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
|
|
33 |
*.zip filter=lfs diff=lfs merge=lfs -text
|
34 |
*.zst filter=lfs diff=lfs merge=lfs -text
|
35 |
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
|
|
|
33 |
*.zip filter=lfs diff=lfs merge=lfs -text
|
34 |
*.zst filter=lfs diff=lfs merge=lfs -text
|
35 |
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
36 |
+
libfacesdk2.so filter=lfs diff=lfs merge=lfs -text
|
Dockerfile
ADDED
@@ -0,0 +1,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
FROM openvino/ubuntu20_runtime:2022.3.0
|
2 |
+
USER root
|
3 |
+
|
4 |
+
RUN apt-get update -y
|
5 |
+
RUN apt-get install -y libcurl4-openssl-dev libssl-dev libgomp1 libpugixml-dev
|
6 |
+
|
7 |
+
RUN mkdir -p /root/kby-ai-face
|
8 |
+
WORKDIR /root/kby-ai-face
|
9 |
+
COPY ./libfacesdk2.so .
|
10 |
+
COPY ./libimutils.so /usr/lib/libimutils.so
|
11 |
+
COPY ./facesdk.py .
|
12 |
+
COPY ./facebox.py .
|
13 |
+
COPY ./app.py .
|
14 |
+
COPY ./demo.py .
|
15 |
+
COPY ./run.sh .
|
16 |
+
COPY ./face_examples ./face_examples
|
17 |
+
COPY ./requirements.txt .
|
18 |
+
COPY ./data ./data
|
19 |
+
RUN pip3 install -r requirements.txt
|
20 |
+
CMD ["./run.sh"]
|
21 |
+
EXPOSE 8080 9000
|
app.py
ADDED
@@ -0,0 +1,223 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import sys
|
2 |
+
sys.path.append('.')
|
3 |
+
|
4 |
+
import os
|
5 |
+
import numpy as np
|
6 |
+
import base64
|
7 |
+
import io
|
8 |
+
|
9 |
+
from PIL import Image
|
10 |
+
from flask import Flask, request, jsonify
|
11 |
+
from facesdk import getMachineCode
|
12 |
+
from facesdk import setActivation
|
13 |
+
from facesdk import initSDK
|
14 |
+
from facesdk import faceDetection
|
15 |
+
from facesdk import templateExtraction
|
16 |
+
from facesdk import similarityCalculation
|
17 |
+
from facebox import FaceBox
|
18 |
+
|
19 |
+
verifyThreshold = 0.67
|
20 |
+
|
21 |
+
maxFaceCount = 1
|
22 |
+
|
23 |
+
licensePath = "license.txt"
|
24 |
+
license = ""
|
25 |
+
|
26 |
+
# Get a specific environment variable by name
|
27 |
+
license = os.environ.get("LICENSE")
|
28 |
+
|
29 |
+
# Check if the variable exists
|
30 |
+
if license is not None:
|
31 |
+
print("Value of LICENSE:", license)
|
32 |
+
else:
|
33 |
+
license = ""
|
34 |
+
try:
|
35 |
+
with open(licensePath, 'r') as file:
|
36 |
+
license = file.read().strip()
|
37 |
+
except IOError as exc:
|
38 |
+
print("failed to open license.txt: ", exc.errno)
|
39 |
+
print("license: ", license)
|
40 |
+
|
41 |
+
machineCode = getMachineCode()
|
42 |
+
print("machineCode: ", machineCode.decode('utf-8'))
|
43 |
+
|
44 |
+
|
45 |
+
ret = setActivation(license.encode('utf-8'))
|
46 |
+
print("activation: ", ret)
|
47 |
+
|
48 |
+
ret = initSDK("data".encode('utf-8'))
|
49 |
+
print("init: ", ret)
|
50 |
+
|
51 |
+
app = Flask(__name__)
|
52 |
+
|
53 |
+
@app.route('/compare_face', methods=['POST'])
|
54 |
+
def compare_face():
|
55 |
+
result = "None"
|
56 |
+
similarity = -1
|
57 |
+
face1 = None
|
58 |
+
face2 = None
|
59 |
+
|
60 |
+
file1 = request.files['file1']
|
61 |
+
file2 = request.files['file2']
|
62 |
+
|
63 |
+
try:
|
64 |
+
image1 = Image.open(file1).convert('RGB')
|
65 |
+
except:
|
66 |
+
result = "Failed to open file1"
|
67 |
+
response = jsonify({"compare_result": result, "compare_similarity": similarity, "face1": face1, "face2": face2})
|
68 |
+
|
69 |
+
response.status_code = 200
|
70 |
+
response.headers["Content-Type"] = "application/json; charset=utf-8"
|
71 |
+
return response
|
72 |
+
|
73 |
+
|
74 |
+
try:
|
75 |
+
image2 = Image.open(file2).convert('RGB')
|
76 |
+
except:
|
77 |
+
result = "Failed to open file2"
|
78 |
+
response = jsonify({"compare_result": result, "compare_similarity": similarity, "face1": face1, "face2": face2})
|
79 |
+
|
80 |
+
response.status_code = 200
|
81 |
+
response.headers["Content-Type"] = "application/json; charset=utf-8"
|
82 |
+
return response
|
83 |
+
|
84 |
+
image_np1 = np.asarray(image1)
|
85 |
+
image_np2 = np.asarray(image2)
|
86 |
+
|
87 |
+
faceBoxes1 = (FaceBox * maxFaceCount)()
|
88 |
+
faceCount1 = faceDetection(image_np1, image_np1.shape[1], image_np1.shape[0], faceBoxes1, maxFaceCount)
|
89 |
+
|
90 |
+
faceBoxes2 = (FaceBox * maxFaceCount)()
|
91 |
+
faceCount2 = faceDetection(image_np2, image_np2.shape[1], image_np2.shape[0], faceBoxes2, maxFaceCount)
|
92 |
+
|
93 |
+
if faceCount1 == 1 and faceCount2 == 1:
|
94 |
+
templateExtraction(image_np1, image_np1.shape[1], image_np1.shape[0], faceBoxes1[0])
|
95 |
+
templateExtraction(image_np2, image_np2.shape[1], image_np2.shape[0], faceBoxes2[0])
|
96 |
+
similarity = similarityCalculation(faceBoxes1[0].templates, faceBoxes2[0].templates)
|
97 |
+
if similarity > verifyThreshold:
|
98 |
+
result = "Same person"
|
99 |
+
else:
|
100 |
+
result = "Different person"
|
101 |
+
elif faceCount1 == 0:
|
102 |
+
result = "No face1"
|
103 |
+
elif faceCount2 == 0:
|
104 |
+
result = "No face2"
|
105 |
+
|
106 |
+
if faceCount1 == 1:
|
107 |
+
landmark_68 = []
|
108 |
+
for j in range(68):
|
109 |
+
landmark_68.append({"x": faceBoxes1[0].landmark_68[j * 2], "y": faceBoxes1[0].landmark_68[j * 2 + 1]})
|
110 |
+
|
111 |
+
face1 = {"x1": faceBoxes1[0].x1, "y1": faceBoxes1[0].y1, "x2": faceBoxes1[0].x2, "y2": faceBoxes1[0].y2,
|
112 |
+
"yaw": faceBoxes1[0].yaw, "roll": faceBoxes1[0].roll, "pitch": faceBoxes1[0].pitch,
|
113 |
+
"face_quality": faceBoxes1[0].face_quality, "face_luminance": faceBoxes1[0].face_luminance, "eye_dist": faceBoxes1[0].eye_dist,
|
114 |
+
"left_eye_closed": faceBoxes1[0].left_eye_closed, "right_eye_closed": faceBoxes1[0].right_eye_closed,
|
115 |
+
"face_occlusion": faceBoxes1[0].face_occlusion, "mouth_opened": faceBoxes1[0].mouth_opened,
|
116 |
+
"landmark_68": landmark_68}
|
117 |
+
|
118 |
+
if faceCount2 == 1:
|
119 |
+
landmark_68 = []
|
120 |
+
for j in range(68):
|
121 |
+
landmark_68.append({"x": faceBoxes2[0].landmark_68[j * 2], "y": faceBoxes2[0].landmark_68[j * 2 + 1]})
|
122 |
+
|
123 |
+
face2 = {"x1": faceBoxes2[0].x1, "y1": faceBoxes2[0].y1, "x2": faceBoxes2[0].x2, "y2": faceBoxes2[0].y2,
|
124 |
+
"yaw": faceBoxes2[0].yaw, "roll": faceBoxes2[0].roll, "pitch": faceBoxes2[0].pitch,
|
125 |
+
"face_quality": faceBoxes2[0].face_quality, "face_luminance": faceBoxes2[0].face_luminance, "eye_dist": faceBoxes2[0].eye_dist,
|
126 |
+
"left_eye_closed": faceBoxes2[0].left_eye_closed, "right_eye_closed": faceBoxes2[0].right_eye_closed,
|
127 |
+
"face_occlusion": faceBoxes2[0].face_occlusion, "mouth_opened": faceBoxes2[0].mouth_opened,
|
128 |
+
"landmark_68": landmark_68}
|
129 |
+
|
130 |
+
response = jsonify({"compare_result": result, "compare_similarity": similarity, "face1": face1, "face2": face2})
|
131 |
+
|
132 |
+
response.status_code = 200
|
133 |
+
response.headers["Content-Type"] = "application/json; charset=utf-8"
|
134 |
+
return response
|
135 |
+
|
136 |
+
@app.route('/compare_face_base64', methods=['POST'])
|
137 |
+
def compare_face_base64():
|
138 |
+
result = "None"
|
139 |
+
similarity = -1
|
140 |
+
face1 = None
|
141 |
+
face2 = None
|
142 |
+
|
143 |
+
content = request.get_json()
|
144 |
+
|
145 |
+
try:
|
146 |
+
imageBase64_1 = content['base64_1']
|
147 |
+
image_data1 = base64.b64decode(imageBase64_1)
|
148 |
+
image1 = Image.open(io.BytesIO(image_data1)).convert('RGB')
|
149 |
+
except:
|
150 |
+
result = "Failed to open file1"
|
151 |
+
response = jsonify({"compare_result": result, "compare_similarity": similarity, "face1": face1, "face2": face2})
|
152 |
+
|
153 |
+
response.status_code = 200
|
154 |
+
response.headers["Content-Type"] = "application/json; charset=utf-8"
|
155 |
+
return response
|
156 |
+
|
157 |
+
try:
|
158 |
+
imageBase64_2 = content['base64_2']
|
159 |
+
image_data2 = base64.b64decode(imageBase64_2)
|
160 |
+
image2 = Image.open(io.BytesIO(image_data2)).convert('RGB')
|
161 |
+
except IOError as exc:
|
162 |
+
result = "Failed to open file2"
|
163 |
+
response = jsonify({"compare_result": result, "compare_similarity": similarity, "face1": face1, "face2": face2})
|
164 |
+
|
165 |
+
response.status_code = 200
|
166 |
+
response.headers["Content-Type"] = "application/json; charset=utf-8"
|
167 |
+
return response
|
168 |
+
|
169 |
+
image_np1 = np.asarray(image1)
|
170 |
+
image_np2 = np.asarray(image2)
|
171 |
+
|
172 |
+
faceBoxes1 = (FaceBox * maxFaceCount)()
|
173 |
+
faceCount1 = faceDetection(image_np1, image_np1.shape[1], image_np1.shape[0], faceBoxes1, maxFaceCount)
|
174 |
+
|
175 |
+
faceBoxes2 = (FaceBox * maxFaceCount)()
|
176 |
+
faceCount2 = faceDetection(image_np2, image_np2.shape[1], image_np2.shape[0], faceBoxes2, maxFaceCount)
|
177 |
+
|
178 |
+
if faceCount1 == 1 and faceCount2 == 1:
|
179 |
+
templateExtraction(image_np1, image_np1.shape[1], image_np1.shape[0], faceBoxes1[0])
|
180 |
+
templateExtraction(image_np2, image_np2.shape[1], image_np2.shape[0], faceBoxes2[0])
|
181 |
+
similarity = similarityCalculation(faceBoxes1[0].templates, faceBoxes2[0].templates)
|
182 |
+
if similarity > verifyThreshold:
|
183 |
+
result = "Same person"
|
184 |
+
else:
|
185 |
+
result = "Different person"
|
186 |
+
elif faceCount1 == 0:
|
187 |
+
result = "No face1"
|
188 |
+
elif faceCount2 == 0:
|
189 |
+
result = "No face2"
|
190 |
+
|
191 |
+
if faceCount1 == 1:
|
192 |
+
landmark_68 = []
|
193 |
+
for j in range(68):
|
194 |
+
landmark_68.append({"x": faceBoxes1[0].landmark_68[j * 2], "y": faceBoxes1[0].landmark_68[j * 2 + 1]})
|
195 |
+
|
196 |
+
face1 = {"x1": faceBoxes1[0].x1, "y1": faceBoxes1[0].y1, "x2": faceBoxes1[0].x2, "y2": faceBoxes1[0].y2,
|
197 |
+
"yaw": faceBoxes1[0].yaw, "roll": faceBoxes1[0].roll, "pitch": faceBoxes1[0].pitch,
|
198 |
+
"face_quality": faceBoxes1[0].face_quality, "face_luminance": faceBoxes1[0].face_luminance, "eye_dist": faceBoxes1[0].eye_dist,
|
199 |
+
"left_eye_closed": faceBoxes1[0].left_eye_closed, "right_eye_closed": faceBoxes1[0].right_eye_closed,
|
200 |
+
"face_occlusion": faceBoxes1[0].face_occlusion, "mouth_opened": faceBoxes1[0].mouth_opened,
|
201 |
+
"landmark_68": landmark_68}
|
202 |
+
|
203 |
+
if faceCount2 == 1:
|
204 |
+
landmark_68 = []
|
205 |
+
for j in range(68):
|
206 |
+
landmark_68.append({"x": faceBoxes2[0].landmark_68[j * 2], "y": faceBoxes2[0].landmark_68[j * 2 + 1]})
|
207 |
+
|
208 |
+
face2 = {"x1": faceBoxes2[0].x1, "y1": faceBoxes2[0].y1, "x2": faceBoxes2[0].x2, "y2": faceBoxes2[0].y2,
|
209 |
+
"yaw": faceBoxes2[0].yaw, "roll": faceBoxes2[0].roll, "pitch": faceBoxes2[0].pitch,
|
210 |
+
"face_quality": faceBoxes2[0].face_quality, "face_luminance": faceBoxes2[0].face_luminance, "eye_dist": faceBoxes2[0].eye_dist,
|
211 |
+
"left_eye_closed": faceBoxes2[0].left_eye_closed, "right_eye_closed": faceBoxes2[0].right_eye_closed,
|
212 |
+
"face_occlusion": faceBoxes2[0].face_occlusion, "mouth_opened": faceBoxes2[0].mouth_opened,
|
213 |
+
"landmark_68": landmark_68}
|
214 |
+
|
215 |
+
response = jsonify({"compare_result": result, "compare_similarity": similarity, "face1": face1, "face2": face2})
|
216 |
+
|
217 |
+
response.status_code = 200
|
218 |
+
response.headers["Content-Type"] = "application/json; charset=utf-8"
|
219 |
+
return response
|
220 |
+
|
221 |
+
if __name__ == '__main__':
|
222 |
+
port = int(os.environ.get("PORT", 8080))
|
223 |
+
app.run(host='0.0.0.0', port=port)
|
data/detect.bin
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:0b505c320dd8add047f107549849a307d0c6f518f01c1d3402bce9e13a765146
|
3 |
+
size 28463173
|
data/eye.bin
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:c8281f9113d6fa4cc2f94ac8f4fdd3dbb7004b27adad39ac7175a802f9aaeed1
|
3 |
+
size 2446608
|
data/landmark.bin
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:b95b4e6043add90c16f97f00990973a6f8c6f3511491358772e734aa20f606bd
|
3 |
+
size 10828783
|
data/templates.bin
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:d953ac95ac9dcccc794104d32f0d54ba067c55a10a9546d308d67096d6ee2ca0
|
3 |
+
size 324888336
|
demo.py
ADDED
@@ -0,0 +1,141 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import gradio as gr
|
2 |
+
import requests
|
3 |
+
import datadog_api_client
|
4 |
+
from PIL import Image
|
5 |
+
|
6 |
+
def compare_face(frame1, frame2):
|
7 |
+
url = "http://127.0.0.1:8080/compare_face"
|
8 |
+
files = {'file1': open(frame1, 'rb'), 'file2': open(frame2, 'rb')}
|
9 |
+
|
10 |
+
r = requests.post(url=url, files=files)
|
11 |
+
|
12 |
+
html = None
|
13 |
+
faces = None
|
14 |
+
|
15 |
+
compare_result = r.json().get('compare_result')
|
16 |
+
compare_similarity = r.json().get('compare_similarity')
|
17 |
+
|
18 |
+
html = ("<table>"
|
19 |
+
"<tr>"
|
20 |
+
"<th>Compare Result</th>"
|
21 |
+
"<th>Value</th>"
|
22 |
+
"</tr>"
|
23 |
+
"<tr>"
|
24 |
+
"<td>Result</td>"
|
25 |
+
"<td>{compare_result}</td>"
|
26 |
+
"</tr>"
|
27 |
+
"<tr>"
|
28 |
+
"<td>Similarity</td>"
|
29 |
+
"<td>{compare_similarity}</td>"
|
30 |
+
"</tr>"
|
31 |
+
"</table>".format(compare_result=compare_result, compare_similarity=compare_similarity))
|
32 |
+
|
33 |
+
try:
|
34 |
+
image1 = Image.open(frame1)
|
35 |
+
image2 = Image.open(frame2)
|
36 |
+
|
37 |
+
face1 = None
|
38 |
+
face2 = None
|
39 |
+
|
40 |
+
if r.json().get('face1') is not None:
|
41 |
+
face = r.json().get('face1')
|
42 |
+
x1 = face.get('x1')
|
43 |
+
y1 = face.get('y1')
|
44 |
+
x2 = face.get('x2')
|
45 |
+
y2 = face.get('y2')
|
46 |
+
|
47 |
+
if x1 < 0:
|
48 |
+
x1 = 0
|
49 |
+
if y1 < 0:
|
50 |
+
y1 = 0
|
51 |
+
if x2 >= image1.width:
|
52 |
+
x2 = image1.width - 1
|
53 |
+
if y2 >= image1.height:
|
54 |
+
y2 = image1.height - 1
|
55 |
+
|
56 |
+
face1 = image1.crop((x1, y1, x2, y2))
|
57 |
+
face_image_ratio = face1.width / float(face1.height)
|
58 |
+
resized_w = int(face_image_ratio * 150)
|
59 |
+
resized_h = 150
|
60 |
+
|
61 |
+
face1 = face1.resize((int(resized_w), int(resized_h)))
|
62 |
+
|
63 |
+
if r.json().get('face2') is not None:
|
64 |
+
face = r.json().get('face2')
|
65 |
+
x1 = face.get('x1')
|
66 |
+
y1 = face.get('y1')
|
67 |
+
x2 = face.get('x2')
|
68 |
+
y2 = face.get('y2')
|
69 |
+
|
70 |
+
if x1 < 0:
|
71 |
+
x1 = 0
|
72 |
+
if y1 < 0:
|
73 |
+
y1 = 0
|
74 |
+
if x2 >= image2.width:
|
75 |
+
x2 = image2.width - 1
|
76 |
+
if y2 >= image2.height:
|
77 |
+
y2 = image2.height - 1
|
78 |
+
|
79 |
+
face2 = image2.crop((x1, y1, x2, y2))
|
80 |
+
face_image_ratio = face2.width / float(face2.height)
|
81 |
+
resized_w = int(face_image_ratio * 150)
|
82 |
+
resized_h = 150
|
83 |
+
|
84 |
+
face2 = face2.resize((int(resized_w), int(resized_h)))
|
85 |
+
|
86 |
+
if face1 is not None and face2 is not None:
|
87 |
+
new_image = Image.new('RGB',(face1.width + face2.width + 10, 150), (80,80,80))
|
88 |
+
|
89 |
+
new_image.paste(face1,(0,0))
|
90 |
+
new_image.paste(face2,(face1.width + 10, 0))
|
91 |
+
faces = new_image.copy()
|
92 |
+
elif face1 is not None and face2 is None:
|
93 |
+
new_image = Image.new('RGB',(face1.width + face1.width + 10, 150), (80,80,80))
|
94 |
+
|
95 |
+
new_image.paste(face1,(0,0))
|
96 |
+
faces = new_image.copy()
|
97 |
+
elif face1 is None and face2 is not None:
|
98 |
+
new_image = Image.new('RGB',(face2.width + face2.width + 10, 150), (80,80,80))
|
99 |
+
|
100 |
+
new_image.paste(face2,(face2.width + 10, 0))
|
101 |
+
faces = new_image.copy()
|
102 |
+
|
103 |
+
except:
|
104 |
+
pass
|
105 |
+
|
106 |
+
return [faces, html]
|
107 |
+
|
108 |
+
with gr.Blocks() as demo:
|
109 |
+
gr.Markdown(
|
110 |
+
"""
|
111 |
+
# KBY-AI
|
112 |
+
We offer SDKs for Face Recognition, Face Liveness Detection(Face Anti-Spoofing), and ID Card Recognition.<br/>
|
113 |
+
Besides that, we can provide several AI models and development services in machine learning.
|
114 |
+
|
115 |
+
## Simple Installation & Simple API
|
116 |
+
```
|
117 |
+
sudo docker pull kbyai/face-recognition:latest
|
118 |
+
sudo docker run -e LICENSE="xxxxx" -p 8081:8080 -p 9001:9000 kbyai/face-recognition:latest
|
119 |
+
```
|
120 |
+
## KYC Verification Demo
|
121 |
+
https://github.com/kby-ai/KYC-Verification
|
122 |
+
"""
|
123 |
+
)
|
124 |
+
with gr.TabItem("Face Recognition"):
|
125 |
+
with gr.Row():
|
126 |
+
with gr.Column():
|
127 |
+
compare_face_input1 = gr.Image(type='filepath')
|
128 |
+
gr.Examples(['face_examples/1.jpg', 'face_examples/3.jpg', 'face_examples/5.jpg', 'face_examples/7.jpg', 'face_examples/9.jpg'],
|
129 |
+
inputs=compare_face_input1)
|
130 |
+
compare_face_button = gr.Button("Compare Face")
|
131 |
+
with gr.Column():
|
132 |
+
compare_face_input2 = gr.Image(type='filepath')
|
133 |
+
gr.Examples(['face_examples/2.jpg', 'face_examples/4.jpg', 'face_examples/6.jpg', 'face_examples/8.jpg', 'face_examples/10.jpg'],
|
134 |
+
inputs=compare_face_input2)
|
135 |
+
with gr.Column():
|
136 |
+
compare_face_output = gr.Image(type="pil").style(height=150)
|
137 |
+
compare_result_output = gr.HTML(label='Result')
|
138 |
+
|
139 |
+
compare_face_button.click(compare_face, inputs=[compare_face_input1, compare_face_input2], outputs=[compare_face_output, compare_result_output])
|
140 |
+
|
141 |
+
demo.launch(server_name="0.0.0.0", server_port=9000)
|
face_examples/1.jpg
ADDED
face_examples/10.jpg
ADDED
face_examples/2.jpg
ADDED
face_examples/3.jpg
ADDED
face_examples/4.jpg
ADDED
face_examples/5.jpg
ADDED
face_examples/6.jpg
ADDED
face_examples/7.jpg
ADDED
face_examples/8.jpg
ADDED
face_examples/9.jpg
ADDED
facebox.py
ADDED
@@ -0,0 +1,11 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from ctypes import *
|
2 |
+
|
3 |
+
class FaceBox(Structure):
|
4 |
+
_fields_ = [("x1", c_int32), ("y1", c_int32), ("x2", c_int32), ("y2", c_int32),
|
5 |
+
("yaw", c_float), ("roll", c_float), ("pitch", c_float),
|
6 |
+
("face_quality", c_float), ("face_luminance", c_float), ("eye_dist", c_float),
|
7 |
+
("left_eye_closed", c_float), ("right_eye_closed", c_float),
|
8 |
+
("face_occlusion", c_float), ("mouth_opened", c_float),
|
9 |
+
("landmark_68", c_float * 136),
|
10 |
+
("templates", c_ubyte * 2048)
|
11 |
+
]
|
facesdk.py
ADDED
@@ -0,0 +1,32 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import os
|
2 |
+
|
3 |
+
from ctypes import *
|
4 |
+
from numpy.ctypeslib import ndpointer
|
5 |
+
from facebox import FaceBox
|
6 |
+
|
7 |
+
libPath = os.path.abspath(os.path.dirname(__file__)) + '/libfacesdk2.so'
|
8 |
+
facesdk = cdll.LoadLibrary(libPath)
|
9 |
+
|
10 |
+
getMachineCode = facesdk.getMachineCode
|
11 |
+
getMachineCode.argtypes = []
|
12 |
+
getMachineCode.restype = c_char_p
|
13 |
+
|
14 |
+
setActivation = facesdk.setActivation
|
15 |
+
setActivation.argtypes = [c_char_p]
|
16 |
+
setActivation.restype = c_int32
|
17 |
+
|
18 |
+
initSDK = facesdk.initSDK
|
19 |
+
initSDK.argtypes = [c_char_p]
|
20 |
+
initSDK.restype = c_int32
|
21 |
+
|
22 |
+
faceDetection = facesdk.faceDetection
|
23 |
+
faceDetection.argtypes = [ndpointer(c_ubyte, flags='C_CONTIGUOUS'), c_int32, c_int32, POINTER(FaceBox), c_int32]
|
24 |
+
faceDetection.restype = c_int32
|
25 |
+
|
26 |
+
templateExtraction = facesdk.templateExtraction
|
27 |
+
templateExtraction.argtypes = [ndpointer(c_ubyte, flags='C_CONTIGUOUS'), c_int32, c_int32, POINTER(FaceBox)]
|
28 |
+
templateExtraction.restype = c_int32
|
29 |
+
|
30 |
+
similarityCalculation = facesdk.similarityCalculation
|
31 |
+
similarityCalculation.argtypes = [c_ubyte * 2048, c_ubyte * 2048]
|
32 |
+
similarityCalculation.restype = c_float
|
libfacesdk2.so
ADDED
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
1 |
+
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:ca1e9a7bbc737ad24d8a2ac5942e5d396529eacb75e6dc15d1ae19102cde996f
|
3 |
+
size 5103016
|
libimutils.so
ADDED
Binary file (412 kB). View file
|
|
libimutils.so_for_ubuntu22
ADDED
Binary file (412 kB). View file
|
|
license.txt
ADDED
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
X3tZBYEsEN2uHpfhqE1ey7bYJxW+pqBE+Niw3KOXnLkGkySze00sGuLI1SwbqsvYXfZ6V4tVa8gc
|
2 |
+
tiLBXVxkagOO6KjLYPLjxZM59gi3RYB8FoNYulaITilxNPu/5QQrRmEGJ7Qef3ewdlIv20IqsZOx
|
3 |
+
NB2vSBEO263OSogqT/lOpCAAUQhyxApY5iJsh6j+aWBSHkgx8XOscEw3x7m+DBHqKy0M6Vncnwla
|
4 |
+
gkY9O53wwCqyTljvUmxIBRYUqdaxND82a0XgGk5armnaK2gRN1zKSW+cNd4s2nUKH07AlEeKCUqz
|
5 |
+
OdzWhwdHQM/ULhAl1Oyyiw7NmUBLC7XmprB8EA==
|
requirements.txt
ADDED
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
flask
|
2 |
+
flask-cors
|
3 |
+
Pillow
|
4 |
+
numpy
|
5 |
+
gradio==3.50.2
|
6 |
+
datadog_api_client
|
run.sh
ADDED
@@ -0,0 +1,5 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
#!/bin/bash
|
2 |
+
|
3 |
+
cd /root/kby-ai-face
|
4 |
+
exec python3 demo.py &
|
5 |
+
exec python3 app.py
|