Zhu-FaceOnLive commited on
Commit
61242aa
·
verified ·
1 Parent(s): c40925a

Upload 20 files

Browse files
.gitattributes CHANGED
@@ -33,3 +33,10 @@ 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
+ examples/3.jpg filter=lfs diff=lfs merge=lfs -text
37
+ lib/libDocSdk.so filter=lfs diff=lfs merge=lfs -text
38
+ lib/libidlivesdk.so filter=lfs diff=lfs merge=lfs -text
39
+ lib/libopenvino_intel_cpu_plugin.so filter=lfs diff=lfs merge=lfs -text
40
+ lib/libopenvino_onnx_frontend.so.2300 filter=lfs diff=lfs merge=lfs -text
41
+ lib/libopenvino.so.2300 filter=lfs diff=lfs merge=lfs -text
42
+ lib/libopenvino.so.2330 filter=lfs diff=lfs merge=lfs -text
Dockerfile ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ FROM ubuntu:22.04
2
+ RUN ln -snf /usr/share/zoneinfo/$CONTAINER_TIMEZONE /etc/localtime && echo $CONTAINER_TIMEZONE > /etc/timezone
3
+ RUN apt-get update && \
4
+ apt-get install -y binutils python3 python3-pip python3-opencv && \
5
+ rm -rf /var/lib/apt/lists/*
6
+
7
+ RUN useradd -m -u 1000 user
8
+ USER user
9
+ ENV PATH="/home/user/.local/bin:$PATH"
10
+
11
+ WORKDIR /app
12
+ COPY --chown=user ./idlivesdk.py .
13
+ COPY --chown=user ./app.py .
14
+ COPY --chown=user ./demo.py .
15
+ COPY --chown=user ./requirements.txt .
16
+ COPY --chown=user ./run.sh .
17
+ COPY --chown=user ./examples ./examples
18
+ COPY --chown=user ./model ./model
19
+ COPY --chown=user ./lib /usr/lib
20
+ COPY --chown=user ./lib/libidlivesdk.so ./lib/libidlivesdk.so
21
+
22
+ ADD https://huggingface.co/datasets/FaceOnLive/IDL-Models/resolve/main/model.tar.gz .
23
+ RUN tar -xvzf ./model.tar.gz -C . && rm ./model.tar.gz
24
+
25
+ RUN chmod -R 777 ./model/
26
+
27
+ RUN pip3 install -r requirements.txt
28
+ RUN chmod a+x run.sh
29
+ CMD ["./run.sh"]
30
+ EXPOSE 7860
app.py ADDED
@@ -0,0 +1,132 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import sys
2
+ sys.path.append('.')
3
+
4
+ import os
5
+ import numpy as np
6
+ import base64
7
+ import json
8
+ import io
9
+
10
+ from PIL import Image, ExifTags
11
+ from flask import Flask, request, jsonify
12
+ from idlivesdk import getHWID
13
+ from idlivesdk import setLicenseKey
14
+ from idlivesdk import initSDK
15
+ from idlivesdk import processImage
16
+
17
+ licenseKeyPath = "license.txt"
18
+ license = os.environ.get("LICENSE_KEY")
19
+
20
+ if license is None:
21
+ try:
22
+ with open(licenseKeyPath, 'r') as file:
23
+ license = file.read().strip()
24
+ except IOError as exc:
25
+ print("failed to open license.txt: ", exc.errno)
26
+ print("License Key: ", license)
27
+
28
+ hwid = getHWID()
29
+ print("HWID: ", hwid.decode('utf-8'))
30
+
31
+ ret = setLicenseKey(license.encode('utf-8'))
32
+ print("Set License: ", ret)
33
+
34
+ ret = initSDK("model".encode('utf-8'))
35
+ print("Init: ", ret)
36
+
37
+ app = Flask(__name__)
38
+
39
+ def apply_exif_rotation(image):
40
+ try:
41
+ exif = image._getexif()
42
+ if exif is not None:
43
+ for orientation in ExifTags.TAGS.keys():
44
+ if ExifTags.TAGS[orientation] == 'Orientation':
45
+ break
46
+
47
+ # Get the orientation value
48
+ orientation = exif.get(orientation, None)
49
+
50
+ # Apply the appropriate rotation based on the orientation
51
+ if orientation == 3:
52
+ image = image.rotate(180, expand=True)
53
+ elif orientation == 6:
54
+ image = image.rotate(270, expand=True)
55
+ elif orientation == 8:
56
+ image = image.rotate(90, expand=True)
57
+
58
+ except AttributeError:
59
+ print("No EXIF data found")
60
+
61
+ return image
62
+
63
+
64
+ @app.route('/process_image', methods=['POST'])
65
+ def process_image():
66
+ file = request.files['image']
67
+
68
+ try:
69
+ image = apply_exif_rotation(Image.open(file)).convert('RGB')
70
+ except:
71
+ result = "Failed to open file"
72
+ response = jsonify({"resultCode": "Error", "result": result})
73
+
74
+ response.status_code = 200
75
+ response.headers["Content-Type"] = "application/json; charset=utf-8"
76
+ return response
77
+
78
+ image_np = np.asarray(image)
79
+ result = processImage(image_np, image_np.shape[1], image_np.shape[0])
80
+
81
+ if result is None:
82
+ result = "Failed to process image"
83
+ response = jsonify({"resultCode": "Error", "result": result})
84
+
85
+ response.status_code = 200
86
+ response.headers["Content-Type"] = "application/json; charset=utf-8"
87
+ return response
88
+ else:
89
+ result_dict = json.loads(result.decode('utf-8'))
90
+ response = jsonify({"resultCode": "Ok", "result": result_dict})
91
+
92
+ response.status_code = 200
93
+ response.headers["Content-Type"] = "application/json; charset=utf-8"
94
+ return response
95
+
96
+ @app.route('/process_image_base64', methods=['POST'])
97
+ def process_image_base64():
98
+ try:
99
+ content = request.get_json()
100
+ base64_image = content['base64']
101
+
102
+ image_data = base64.b64decode(base64_image)
103
+ image = apply_exif_rotation(Image.open(io.BytesIO(image_data))).convert("RGB")
104
+ except:
105
+ result = "Failed to parse base64"
106
+ response = jsonify({"resultCode": "Error", "result": result})
107
+
108
+ response.status_code = 200
109
+ response.headers["Content-Type"] = "application/json; charset=utf-8"
110
+ return response
111
+
112
+ image_np = np.asarray(image)
113
+ result = processImage(image_np, image_np.shape[1], image_np.shape[0])
114
+
115
+ if result is None:
116
+ result = "Failed to process image"
117
+ response = jsonify({"resultCode": "Error", "result": result})
118
+
119
+ response.status_code = 200
120
+ response.headers["Content-Type"] = "application/json; charset=utf-8"
121
+ return response
122
+ else:
123
+ result_dict = json.loads(result.decode('utf-8'))
124
+ response = jsonify({"resultCode": "Ok", "result": result_dict})
125
+
126
+ response.status_code = 200
127
+ response.headers["Content-Type"] = "application/json; charset=utf-8"
128
+ return response
129
+
130
+ if __name__ == '__main__':
131
+ port = int(os.environ.get("PORT", 9000))
132
+ app.run(host='0.0.0.0', port=port)
demo.py ADDED
@@ -0,0 +1,71 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import gradio as gr
3
+ import requests
4
+ import json
5
+ import io
6
+ import base64
7
+ import cv2
8
+ import numpy as np
9
+ from gradio.components import Image
10
+
11
+ screenReplayThreshold = 0.5
12
+ portraitReplaceThreshold = 0.5
13
+ printedCopyThreshold = 0.5
14
+
15
+ def proc_output(result):
16
+ if result.ok:
17
+ json_result = result.json()
18
+ if json_result.get("resultCode") == "Error":
19
+ return {"status": "error", "result": "failed to process image"}
20
+
21
+ process_results = json_result.get("result")
22
+ status = process_results.get("status")
23
+ if status == "Ok":
24
+ screenReply = process_results.get("screenReply")
25
+ portraitReplace = process_results.get("portraitReplace")
26
+ printedCopy = process_results.get("printedCopy")
27
+ detResult = "genuine"
28
+
29
+ # Check for "Spoof" condition
30
+ if screenReply < screenReplayThreshold or portraitReplace < portraitReplaceThreshold or printedCopy < printedCopyThreshold:
31
+ detResult = "spoof"
32
+
33
+ # Update json_result with the modified process_results
34
+ return {"status": "ok", "data": {"result": detResult, "screenreplay_integrity_score": screenReply, "portraitreplace_integrity_score": portraitReplace, "printedcutout_integrity_score": printedCopy}}
35
+
36
+ return {"status": "error", "result": "document not found!"}
37
+ else:
38
+ return {"status": "error", "result": result.text}
39
+
40
+ def id_liveness(path):
41
+ # Convert PIL image to bytes to send in POST request
42
+ img_bytes = io.BytesIO()
43
+ path.save(img_bytes, format="JPEG")
44
+ img_bytes.seek(0)
45
+
46
+ url = "http://127.0.0.1:9000/process_image"
47
+ files = {'image': img_bytes}
48
+ result = requests.post(url=url, files=files)
49
+ return proc_output(result)
50
+
51
+ with gr.Blocks() as demo:
52
+ gr.Markdown(
53
+ """
54
+ # ID Document Liveness Detection
55
+ Contact us at https://faceonlive.com for issues and support.<br/><br/>
56
+ ** For security and privacy, kindly refrain from uploading real ID card or credit card information on this platform.
57
+ """
58
+ )
59
+ with gr.Row():
60
+ with gr.Column():
61
+ image_input = gr.Image(type='pil')
62
+ gr.Examples(['examples/1.jpg', 'examples/2.jpg', 'examples/3.jpg'],
63
+ inputs=image_input)
64
+ process_button = gr.Button("ID Liveness Detection")
65
+
66
+ with gr.Column():
67
+ json_output = gr.JSON()
68
+
69
+ process_button.click(id_liveness, inputs=image_input, outputs=[json_output])
70
+
71
+ demo.launch(server_name="0.0.0.0")
examples/1.jpg ADDED
examples/2.jpg ADDED
examples/3.jpg ADDED

Git LFS Details

  • SHA256: f7256cbe838aada39142d118ee8d670a301ea4e3c7edc3729490d2bbd706ade6
  • Pointer size: 132 Bytes
  • Size of remote file: 1.59 MB
idlivesdk.py ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+
3
+ from ctypes import *
4
+ from numpy.ctypeslib import ndpointer
5
+
6
+ libPath = os.path.abspath(os.path.dirname(__file__)) + '/lib/idlivesdk.so'
7
+ libidlivesdk = cdll.LoadLibrary(libPath)
8
+
9
+ getHWID = libidlivesdk.getHWID
10
+ getHWID.argtypes = []
11
+ getHWID.restype = c_char_p
12
+
13
+ setLicenseKey = libidlivesdk.setLicenseKey
14
+ setLicenseKey.argtypes = [c_char_p]
15
+ setLicenseKey.restype = c_int32
16
+
17
+ initSDK = libidlivesdk.initSDK
18
+ initSDK.argtypes = [c_char_p]
19
+ initSDK.restype = c_int32
20
+
21
+ processImage = libidlivesdk.processImage
22
+ processImage.argtypes = [ndpointer(c_ubyte, flags='C_CONTIGUOUS'), c_int32, c_int32]
23
+ processImage.restype = c_char_p
24
+
lib/libDocSdk.so ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:9e4fb0d2e876a1ef5d30ba988ac09d295ce9a38572479ae6dce6cf0c3f2ecb01
3
+ size 22300226
lib/libidlivesdk.so ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:5acf23f4525ca1b24c9ba8e59a37cf72b4a4e601c5fa0d4a0079aae86ac21ee1
3
+ size 4194187
lib/libopenvino.so.2300 ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:42d0084280661a5138d9b2cbfba28c6d0df9e85c9d371b96d471b1e3b403e9cd
3
+ size 21726552
lib/libopenvino.so.2330 ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:3be612fe4606381cfddf1198b3ab1a851c0fdbd8490ddb101577f82b1678ce78
3
+ size 22302048
lib/libopenvino_intel_cpu_plugin.so ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:1de80e57d72249ab45de0f0ab807f729a86360248ca4f4d23c203882e7736f21
3
+ size 45820616
lib/libopenvino_ir_frontend.so.2330 ADDED
Binary file (594 kB). View file
 
lib/libopenvino_onnx_frontend.so.2300 ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:924bb07b0964f3657a51772fc788c2a44d028439d6898d5d7e9ab889f34660de
3
+ size 5568776
lib/libopyenv.so ADDED
Binary file (26.8 kB). View file
 
lib/libopyhas.so ADDED
Binary file (17.2 kB). View file
 
lib/libtbb.so.12 ADDED
Binary file (366 kB). View file
 
lib/plugins.xml ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ <ie>
2
+ <plugins>
3
+ <plugin name="CPU" location="libopenvino_intel_cpu_plugin.so">
4
+ </plugin>
5
+ </plugins>
6
+ </ie>
requirements.txt ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ flask
2
+ flask-cors
3
+ gradio==5.4.0
4
+ datadog_api_client
5
+ opencv-python
6
+ numpy==1.24.4
run.sh ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ #!/bin/bash
2
+
3
+ cd /app
4
+ exec python3 app.py &
5
+ sleep 10
6
+ exec python3 demo.py