cadyderwin commited on
Commit
a9e25c7
·
verified ·
1 Parent(s): cebd886

Upload 13 files

Browse files
Files changed (14) hide show
  1. .gitattributes +2 -0
  2. Dockerfile +17 -0
  3. app.py +105 -0
  4. demo.py +250 -0
  5. examples/1.jpg +0 -0
  6. examples/2.jpg +0 -0
  7. examples/3.jpg +0 -0
  8. lib/libopyidrecog.so +3 -0
  9. lib/libopyocr.so +3 -0
  10. model/data1.bin +3 -0
  11. model/data2.bin +3 -0
  12. opyidrecog.py +24 -0
  13. requirements.txt +4 -0
  14. run.sh +5 -0
.gitattributes CHANGED
@@ -33,3 +33,5 @@ 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
+ lib/libopyidrecog.so filter=lfs diff=lfs merge=lfs -text
37
+ lib/libopyocr.so filter=lfs diff=lfs merge=lfs -text
Dockerfile ADDED
@@ -0,0 +1,17 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ FROM python:3.8-slim
2
+ WORKDIR /home/opyidrecog
3
+ COPY ./opyidrecog.py .
4
+ COPY ./app.py .
5
+ COPY ./demo.py .
6
+ COPY ./license.txt .
7
+ COPY ./requirements.txt .
8
+ COPY ./run.sh .
9
+ COPY ./arial.ttf .
10
+ COPY ./examples ./examples
11
+ COPY ./model ./model
12
+ COPY ./lib /usr/lib
13
+ COPY ./lib/opyidrecog.so ./lib/opyidrecog.so
14
+ RUN pip3 install -r requirements.txt
15
+ RUN chmod a+x run.sh
16
+ CMD ["./run.sh"]
17
+ EXPOSE 9000 7860
app.py ADDED
@@ -0,0 +1,105 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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 opyidrecog import getHWID
13
+ from opyidrecog import setLicenseKey
14
+ from opyidrecog import initSDK
15
+ from opyidrecog import processImage
16
+
17
+ licenseKeyPath = "license.txt"
18
+ license = ""
19
+
20
+ try:
21
+ with open(licenseKeyPath, 'r') as file:
22
+ license = file.read().strip()
23
+ except IOError as exc:
24
+ print("failed to open license.txt: ", exc.errno)
25
+ print("License Key: ", license)
26
+
27
+ hwid = getHWID()
28
+ print("HWID: ", hwid.decode('utf-8'))
29
+
30
+ ret = setLicenseKey(license.encode('utf-8'))
31
+ print("Set License: ", ret)
32
+
33
+ ret = initSDK("model".encode('utf-8'))
34
+ print("Init: ", ret)
35
+
36
+ app = Flask(__name__)
37
+
38
+
39
+ @app.route('/process_image', methods=['POST'])
40
+ def process_image():
41
+ base64_image1 = ""
42
+ base64_image2 = ""
43
+ try:
44
+ file1 = request.files['image1']
45
+ base64_image1 = base64.b64encode(file1.read()).decode('utf-8')
46
+ except:
47
+ result = "Failed to open image1"
48
+ response = jsonify({"resultCode": "Error", "result": result})
49
+
50
+ response.status_code = 200
51
+ response.headers["Content-Type"] = "application/json; charset=utf-8"
52
+ return response
53
+
54
+ try:
55
+ file2 = request.files['image2']
56
+ base64_image2 = base64.b64encode(file2.read()).decode('utf-8')
57
+ except:
58
+ base64_image2 = ""
59
+
60
+ result = processImage(base64_image1.encode('utf-8'), base64_image2.encode('utf-8'))
61
+
62
+ result_dict = json.loads(result.decode('utf-8'))
63
+ response = jsonify({"resultCode": "Ok", "result": result_dict})
64
+
65
+ response.status_code = 200
66
+ response.headers["Content-Type"] = "application/json; charset=utf-8"
67
+ return response
68
+
69
+ @app.route('/process_image_base64', methods=['POST'])
70
+ def process_image_base64():
71
+ base64_image1 = ""
72
+ base64_image2 = ""
73
+
74
+ try:
75
+ content = request.get_json()
76
+ base64_image1 = content['image1_base64']
77
+ except:
78
+ result = "Failed to parse base64"
79
+ response = jsonify({"resultCode": "Error", "result": result})
80
+
81
+ response.status_code = 200
82
+ response.headers["Content-Type"] = "application/json; charset=utf-8"
83
+ return response
84
+
85
+ try:
86
+ content = request.get_json()
87
+ base64_image2 = content['image2_base64']
88
+ except:
89
+ base64_image2 = ""
90
+
91
+ image_np = np.asarray(image)
92
+ result = processImage(image_np, image_np.shape[1], image_np.shape[0])
93
+
94
+ result = processImage(base64_image1.encode('utf-8'), base64_image2.encode('utf-8'))
95
+
96
+ result_dict = json.loads(result.decode('utf-8'))
97
+ response = jsonify({"resultCode": "Ok", "result": result_dict})
98
+
99
+ response.status_code = 200
100
+ response.headers["Content-Type"] = "application/json; charset=utf-8"
101
+ return response
102
+
103
+ if __name__ == '__main__':
104
+ port = int(os.environ.get("PORT", 9000))
105
+ app.run(host='0.0.0.0', port=port)
demo.py ADDED
@@ -0,0 +1,250 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import gradio as gr
3
+ import requests
4
+ import json
5
+ import io
6
+ from gradio.components import Image
7
+ from PIL import Image as PILImage, ImageDraw, ImageFont # This import may be needed if you're processing images
8
+
9
+ from PIL import Image
10
+
11
+ def process_image(image1, image2):
12
+ try:
13
+ img_bytes1 = io.BytesIO()
14
+ image1.save(img_bytes1, format="JPEG")
15
+ img_bytes1.seek(0)
16
+ except:
17
+ return ["Failed to open image", {"resultCode": "Error", "result": "Failed to open image"}]
18
+
19
+ try:
20
+ img_bytes2 = io.BytesIO()
21
+ image2.save(img_bytes2, format="JPEG")
22
+ img_bytes2.seek(0)
23
+ except:
24
+ pass
25
+
26
+ url = "http://127.0.0.1:9000/process_image"
27
+ files = {'image1': img_bytes1, 'image2': img_bytes2}
28
+ result = requests.post(url=url, files=files)
29
+ if result.ok:
30
+ json_result = result.json()
31
+ if json_result.get("resultCode") == "Error":
32
+ return ["Failed to process image", {"resultCode": "Error", "result": "Failed to process image"}]
33
+
34
+ html = None
35
+ images = None
36
+ mrz = None
37
+ barcode = None
38
+
39
+ r = json_result.get("result", {})
40
+ table_value = ""
41
+
42
+ if r.get('MRZ') is not None:
43
+ mrz = r.get('MRZ')
44
+
45
+ if r.get('Barcode') is not None:
46
+ barcode = r.get('Barcode')
47
+
48
+ for key, value in r.items():
49
+ if key == 'Images' or key == 'MRZ' or key == 'Barcode':
50
+ continue
51
+
52
+ mrz_value = ''
53
+ if mrz is not None and mrz.get(key) is not None:
54
+ mrz_value = mrz[key]
55
+ del mrz[key]
56
+
57
+ barcode_value = ''
58
+ if barcode is not None and barcode.get(key) is not None:
59
+ barcode_value = barcode[key]
60
+ del barcode[key]
61
+
62
+ if mrz is not None and barcode is not None:
63
+ row_value = ("<tr>"
64
+ "<td>{key}</td>"
65
+ "<td>{value}</td>"
66
+ "<td>{mrz_value}</td>"
67
+ "<td>{barcode_value}</td>"
68
+ "</tr>".format(key=key, value=value, mrz_value=mrz_value, barcode_value=barcode_value))
69
+ elif mrz is not None:
70
+ row_value = ("<tr>"
71
+ "<td>{key}</td>"
72
+ "<td>{value}</td>"
73
+ "<td>{mrz_value}</td>"
74
+ "</tr>".format(key=key, value=value, mrz_value=mrz_value))
75
+ elif barcode is not None:
76
+ row_value = ("<tr>"
77
+ "<td>{key}</td>"
78
+ "<td>{value}</td>"
79
+ "<td>{barcode_value}</td>"
80
+ "</tr>".format(key=key, value=value, barcode_value=barcode_value))
81
+ else:
82
+ row_value = ("<tr>"
83
+ "<td>{key}</td>"
84
+ "<td>{value}</td>"
85
+ "</tr>".format(key=key, value=value))
86
+
87
+ table_value = table_value + row_value
88
+
89
+ if mrz is not None and barcode is not None:
90
+ for key, value in mrz.items():
91
+ if key == 'MRZ':
92
+ value = value.replace('<', '&lt;')
93
+ value = value.replace(',', '<p>')
94
+
95
+ row_value = ("<tr>"
96
+ "<td>{key}</td>"
97
+ "<td>{value}</td>"
98
+ "<td>{mrz_value}</td>"
99
+ "<td></td>"
100
+ "</tr>".format(key=key, value='', mrz_value=value))
101
+ table_value = table_value + row_value
102
+
103
+ for key, value in barcode.items():
104
+ if key == 'Barcode':
105
+ value = value.replace('<', '&lt;')
106
+ value = value.replace(',', '<p>')
107
+
108
+ row_value = ("<tr>"
109
+ "<td>{key}</td>"
110
+ "<td>{value}</td>"
111
+ "<td></td>"
112
+ "<td>{barcode_value}</td>"
113
+ "</tr>".format(key=key, value='', barcode_value=value))
114
+ table_value = table_value + row_value
115
+ elif mrz is not None:
116
+ for key, value in mrz.items():
117
+ if key == 'MRZ':
118
+ value = value.replace('<', '&lt;')
119
+ value = value.replace(',', '<p>')
120
+
121
+ row_value = ("<tr>"
122
+ "<td>{key}</td>"
123
+ "<td>{value}</td>"
124
+ "<td>{mrz_value}</td>"
125
+ "</tr>".format(key=key, value='', mrz_value=value))
126
+ table_value = table_value + row_value
127
+ elif barcode is not None:
128
+ for key, value in barcode.items():
129
+ if key == 'Barcode':
130
+ value = value.replace('<', '&lt;')
131
+ value = value.replace(',', '<p>')
132
+
133
+ row_value = ("<tr>"
134
+ "<td>{key}</td>"
135
+ "<td>{value}</td>"
136
+ "<td>{barcode_value}</td>"
137
+ "</tr>".format(key=key, value='', barcode_value=value))
138
+ table_value = table_value + row_value
139
+
140
+ if mrz is not None and barcode is not None:
141
+ html = ("<table>"
142
+ "<tr>"
143
+ "<th>Field</th>"
144
+ "<th>OCR</th>"
145
+ "<th>MRZ</th>"
146
+ "<th>Barcode</th>"
147
+ "</tr>"
148
+ "{table_value}"
149
+ "</table>".format(table_value=table_value))
150
+ elif mrz is not None:
151
+ html = ("<table>"
152
+ "<tr>"
153
+ "<th>Field</th>"
154
+ "<th>OCR</th>"
155
+ "<th>MRZ</th>"
156
+ "</tr>"
157
+ "{table_value}"
158
+ "</table>".format(table_value=table_value))
159
+ elif barcode is not None:
160
+ html = ("<table>"
161
+ "<tr>"
162
+ "<th>Field</th>"
163
+ "<th>OCR</th>"
164
+ "<th>Barcode</th>"
165
+ "</tr>"
166
+ "{table_value}"
167
+ "</table>".format(table_value=table_value))
168
+ else:
169
+ html = ("<table>"
170
+ "<tr>"
171
+ "<th>Field</th>"
172
+ "<th>OCR</th>"
173
+ "</tr>"
174
+ "{table_value}"
175
+ "</table>".format(table_value=table_value))
176
+
177
+
178
+ table_value = ""
179
+ for key, value in r.items():
180
+ if key == 'Images':
181
+ for image_key, image_value in value.items():
182
+ row_value = ("<tr>"
183
+ "<td>{key}</td>"
184
+ "<td><img src=""data:image/png;base64,{base64_image} width = '200' height= '100' /></td>"
185
+ "</tr>".format(key=image_key, base64_image=image_value))
186
+ table_value = table_value + row_value
187
+
188
+ images = ("<table>"
189
+ "<tr>"
190
+ "<th>Field</th>"
191
+ "<th>Image</th>"
192
+ "</tr>"
193
+ "{table_value}"
194
+ "</table>".format(table_value=table_value))
195
+
196
+ return [html + "<br/><br/>" + images, json_result]
197
+ else:
198
+ return [result.text, {"resultCode": "Error", "result": result.text}]
199
+
200
+ with gr.Blocks() as demo:
201
+ gr.Markdown(
202
+ """
203
+ <div style="display: flex;align-items: center;">
204
+ <img alt="Opulentyn Logo" src="https://github.com/user-attachments/assets/5fc78032-bff2-4f7e-a174-7d64b22f506d" width="350"/>
205
+ <div>
206
+ <h1>ID Document Recognition</h1>
207
+ <p>We offer <b>on-premises</b> OCR and liveness check solutions available with a <b>perpetual license</b>.</p>
208
+ </div>
209
+ </div>
210
+
211
+ ## 🤝 Talk to us
212
+
213
+ <div style="display: flex; align-items: center;">
214
+ <a href="https://opulentyn.com" target="_blank">
215
+ <img src="https://img.shields.io/badge/Website-https%3A%2F%2Fopulentyn.com-blue?style=flat&logo=google-chrome&logoColor=white" alt="Website">
216
+ </a>
217
+ &nbsp;&nbsp;&nbsp;&nbsp;
218
+ <a href="mailto:support@opulentyn.com">
219
+ <img src="https://img.shields.io/badge/Email-support%40opulentyn.com-blue?style=flat&logo=gmail&logoColor=white" alt="Email">
220
+ </a>
221
+ &nbsp;&nbsp;&nbsp;&nbsp;
222
+ <a href="https://wa.me/13435013587" target="_blank">
223
+ <img src="https://img.shields.io/badge/WhatsApp-%2B13435013587-blue?logo=whatsapp&logoColor=green" alt="WhatsApp">
224
+ </a>
225
+ &nbsp;&nbsp;&nbsp;&nbsp;
226
+ <a href="https://join.slack.com/t/opulentyn/shared_invite/zt-2s230jtbq-dWBs8XUZcrYim~nUqiimSA" target="_blank">
227
+ <img src="https://img.shields.io/badge/Slack-support--sdk-blueviolet?style=flat&logo=slack&logoColor=white" alt="Slack">
228
+ </a>
229
+ </div>
230
+ """
231
+ )
232
+
233
+ with gr.Row():
234
+ with gr.Column():
235
+ image_input1 = gr.Image(type='pil', label='Front')
236
+ image_input2 = gr.Image(type='pil', label='Back')
237
+ gr.Examples(['examples/1.jpg', 'examples/2.jpg', 'examples/3.jpg'],
238
+ inputs=image_input1)
239
+ process_button = gr.Button("Process")
240
+ with gr.Column():
241
+ with gr.TabItem("Output"):
242
+ html_output = gr.HTML()
243
+ with gr.TabItem("JSON"):
244
+ json_output = gr.JSON()
245
+
246
+ process_button.click(process_image, inputs=[image_input1, image_input2], outputs=[html_output, json_output])
247
+
248
+ gr.HTML('<a href="https://visitorbadge.io/status?path=https%3A%2F%2Fhuggingface.co%2Fspaces%2Fopulentyn%2FMrzOCR"><img src="https://api.visitorbadge.io/api/combined?path=https%3A%2F%2Fhuggingface.co%2Fspaces%2Fopulentyn%2FMrzOCR&countColor=%23263759" /></a>')
249
+
250
+ demo.launch(server_name="0.0.0.0", server_port=7860)
examples/1.jpg ADDED
examples/2.jpg ADDED
examples/3.jpg ADDED
lib/libopyidrecog.so ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:56ed0414ebea3695aa232234a63343398c29c5f4a548dbfe33485e2999064cba
3
+ size 2910123
lib/libopyocr.so ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:25832bf9dfc72bdf374f23df29c03077b8831707acf5636cb9b93667602bb372
3
+ size 97975464
model/data1.bin ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:a58c75df0d7958367bc1b7e1a8a2e9b27a0e49bd761b20a1b95e748c56068c3b
3
+ size 243984360
model/data2.bin ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:480bb5f9aa41f1a6944b75f17523753c73b76dfdf829f20b2f0ec2e2b9a5bbd3
3
+ size 292893244
opyidrecog.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/libopyidrecog.so'
7
+ libopyidrecog = cdll.LoadLibrary(libPath)
8
+
9
+ getHWID = libopyidrecog.getHWID
10
+ getHWID.argtypes = []
11
+ getHWID.restype = c_char_p
12
+
13
+ setLicenseKey = libopyidrecog.setLicenseKey
14
+ setLicenseKey.argtypes = [c_char_p]
15
+ setLicenseKey.restype = c_int32
16
+
17
+ initSDK = libopyidrecog.initSDK
18
+ initSDK.argtypes = [c_char_p]
19
+ initSDK.restype = c_int32
20
+
21
+ processImage = libopyidrecog.processImage
22
+ processImage.argtypes = [c_char_p, c_char_p]
23
+ processImage.restype = c_char_p
24
+
requirements.txt ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ flask
2
+ flask-cors
3
+ gradio
4
+ datadog_api_client
run.sh ADDED
@@ -0,0 +1,5 @@
 
 
 
 
 
 
1
+ #!/bin/bash
2
+
3
+ cd /home/opyidrecog
4
+ exec python3 demo.py &
5
+ exec python3 app.py