cadyderwin commited on
Commit
b83366b
·
verified ·
1 Parent(s): 16a104f

Upload 20 files

Browse files
.gitattributes CHANGED
@@ -33,3 +33,7 @@ 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
+ arial.ttf filter=lfs diff=lfs merge=lfs -text
37
+ lib/libopycardenv.so filter=lfs diff=lfs merge=lfs -text
38
+ lib/libtensorflow_framework.so.1.14.0 filter=lfs diff=lfs merge=lfs -text
39
+ lib/libtensorflow.so.1.14.0 filter=lfs diff=lfs merge=lfs -text
Dockerfile ADDED
@@ -0,0 +1,23 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ FROM python:3.8-slim
2
+ WORKDIR /home/opycard
3
+ COPY ./opycard.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/libopycard.so ./lib/libopycard.so
13
+ COPY ./lib/libopycardenv.so ./lib/libopycardenv.so
14
+ COPY ./lib/libtensorflow_framework.so.1.14.0 /usr/lib/libtensorflow_framework.so.1.14.0
15
+ COPY ./lib/libtensorflow.so.1.14.0 /usr/lib/libtensorflow.so.1.14.0
16
+ RUN ln -s /usr/lib/libtensorflow.so.1.14.0 /usr/lib/libtensorflow.so.1 \
17
+ && ln -s /usr/lib/libtensorflow.so.1.14.0 /usr/lib/libtensorflow.so \
18
+ && ln -s /usr/lib/libtensorflow_framework.so.1.14.0 /usr/lib/libtensorflow_framework.so.1 \
19
+ && ln -s /usr/lib/libtensorflow_framework.so.1.14.0 /usr/lib/libtensorflow_framework.so
20
+ RUN pip3 install -r requirements.txt
21
+ RUN chmod a+x run.sh
22
+ CMD ["./run.sh"]
23
+ EXPOSE 9000 7860
app.py ADDED
@@ -0,0 +1,131 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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 opyalpr import getHWID
13
+ from opyalpr import setLicenseKey
14
+ from opyalpr import initSDK
15
+ from opyalpr 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
+ def apply_exif_rotation(image):
39
+ try:
40
+ exif = image._getexif()
41
+ if exif is not None:
42
+ for orientation in ExifTags.TAGS.keys():
43
+ if ExifTags.TAGS[orientation] == 'Orientation':
44
+ break
45
+
46
+ # Get the orientation value
47
+ orientation = exif.get(orientation, None)
48
+
49
+ # Apply the appropriate rotation based on the orientation
50
+ if orientation == 3:
51
+ image = image.rotate(180, expand=True)
52
+ elif orientation == 6:
53
+ image = image.rotate(270, expand=True)
54
+ elif orientation == 8:
55
+ image = image.rotate(90, expand=True)
56
+
57
+ except AttributeError:
58
+ print("No EXIF data found")
59
+
60
+ return image
61
+
62
+
63
+ @app.route('/process_image', methods=['POST'])
64
+ def process_image():
65
+ file = request.files['image']
66
+
67
+ try:
68
+ image = apply_exif_rotation(Image.open(file)).convert('RGB')
69
+ except:
70
+ result = "Failed to open file"
71
+ response = jsonify({"resultCode": "Error", "result": result})
72
+
73
+ response.status_code = 200
74
+ response.headers["Content-Type"] = "application/json; charset=utf-8"
75
+ return response
76
+
77
+ image_np = np.asarray(image)
78
+ result = processImage(image_np, image_np.shape[1], image_np.shape[0])
79
+
80
+ if result is None:
81
+ result = "Failed to process image"
82
+ response = jsonify({"resultCode": "Error", "result": result})
83
+
84
+ response.status_code = 200
85
+ response.headers["Content-Type"] = "application/json; charset=utf-8"
86
+ return response
87
+ else:
88
+ result_dict = json.loads(result.decode('utf-8'))
89
+ response = jsonify({"resultCode": "Ok", "result": result_dict})
90
+
91
+ response.status_code = 200
92
+ response.headers["Content-Type"] = "application/json; charset=utf-8"
93
+ return response
94
+
95
+ @app.route('/process_image_base64', methods=['POST'])
96
+ def process_image_base64():
97
+ try:
98
+ content = request.get_json()
99
+ base64_image = content['base64']
100
+
101
+ image_data = base64.b64decode(base64_image)
102
+ image = apply_exif_rotation(Image.open(io.BytesIO(image_data))).convert("RGB")
103
+ except:
104
+ result = "Failed to parse base64"
105
+ response = jsonify({"resultCode": "Error", "result": result})
106
+
107
+ response.status_code = 200
108
+ response.headers["Content-Type"] = "application/json; charset=utf-8"
109
+ return response
110
+
111
+ image_np = np.asarray(image)
112
+ result = processImage(image_np, image_np.shape[1], image_np.shape[0])
113
+
114
+ if result is None:
115
+ result = "Failed to process image"
116
+ response = jsonify({"resultCode": "Error", "result": result})
117
+
118
+ response.status_code = 200
119
+ response.headers["Content-Type"] = "application/json; charset=utf-8"
120
+ return response
121
+ else:
122
+ result_dict = json.loads(result.decode('utf-8'))
123
+ response = jsonify({"resultCode": "Ok", "result": result_dict})
124
+
125
+ response.status_code = 200
126
+ response.headers["Content-Type"] = "application/json; charset=utf-8"
127
+ return response
128
+
129
+ if __name__ == '__main__':
130
+ port = int(os.environ.get("PORT", 9000))
131
+ app.run(host='0.0.0.0', port=port)
arial.ttf ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:baa251526d6862712a58e613ef451d8a2b60482142ec6aab1d47fb8e23e21a7c
3
+ size 1045960
demo.py ADDED
@@ -0,0 +1,140 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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 resize_image_with_aspect_ratio(image, target_height):
12
+ # Get original dimensions
13
+ original_width, original_height = image.size
14
+
15
+ # Calculate the new width to maintain aspect ratio
16
+ aspect_ratio = original_width / original_height
17
+ new_width = int(target_height * aspect_ratio)
18
+
19
+ # Resize the image
20
+ resized_image = image.resize((new_width, target_height), Image.LANCZOS)
21
+ return resized_image
22
+
23
+ def draw_text_with_background(draw, text, position, font, text_color="red", bg_color="white", padding=2):
24
+ # Get the bounding box of the text
25
+ bbox = draw.textbbox(position, text, font=font)
26
+
27
+ # Calculate the background rectangle coordinates
28
+ bg_x0, bg_y0, bg_x1, bg_y1 = bbox[0] - padding, bbox[1] - padding, bbox[2] + padding, bbox[3] + padding
29
+
30
+ # Draw the background rectangle
31
+ draw.rectangle([bg_x0, bg_y0, bg_x1, bg_y1], fill=bg_color)
32
+
33
+ # Draw the text on top of the background
34
+ draw.text(position, text, fill=text_color, font=font)
35
+
36
+ def process_image(image):
37
+ # Convert PIL image to bytes to send in POST request
38
+ img_bytes = io.BytesIO()
39
+ image.save(img_bytes, format="JPEG")
40
+ img_bytes.seek(0)
41
+
42
+
43
+ url = "http://127.0.0.1:9000/process_image"
44
+ files = {'image': img_bytes}
45
+ result = requests.post(url=url, files=files)
46
+
47
+ # Font setup (default font)
48
+ try:
49
+ font = ImageFont.truetype("arial.ttf", int(image.size[1] / 30))
50
+ except IOError:
51
+ font = ImageFont.load_default()
52
+
53
+ draw = ImageDraw.Draw(image)
54
+ if result.ok:
55
+ json_result = result.json()
56
+ if json_result.get("resultCode") == "Error":
57
+ return [image, {"resultCode": "Error", "result": "Failed to process image"}]
58
+
59
+ # plates = json_result.get("result", {}).get("plates", [])
60
+ # for plate in plates:
61
+ # number = plate.get("number")
62
+ # left = plate.get("left")
63
+ # top = plate.get("top")
64
+ # right = plate.get("right")
65
+ # bottom = plate.get("bottom")
66
+ # countryCode = plate.get('countryCode')
67
+ # car = plate.get('car')
68
+
69
+ # if car is not None:
70
+ # car_left = car.get('left')
71
+ # car_top = car.get('top')
72
+ # car_right = car.get('right')
73
+ # car_bottom = car.get('bottom')
74
+ # color = car.get('color')
75
+ # madeBy = car.get('madeBy')
76
+ # model = car.get('model')
77
+ # draw.rectangle([car_left, car_top, car_right, car_bottom], outline="white", width=3)
78
+ # draw_text_with_background(draw, color + "," + madeBy + "," + model, (car_left, car_top - 10), font, text_color="blue", bg_color="white")
79
+
80
+
81
+ # # Draw rectangle and plate number
82
+ # if left is not None:
83
+ # draw.rectangle([left, top, right, bottom], outline="green", width=3)
84
+ # draw_text_with_background(draw, number + "," + countryCode, (left, top - 10), font, text_color="green", bg_color="white")
85
+
86
+
87
+ return [image, json_result]
88
+ else:
89
+ return [image, {"resultCode": "Error", "result": result.text}]
90
+
91
+ with gr.Blocks() as demo:
92
+ gr.Markdown(
93
+ """
94
+ <div style="display: flex;align-items: center;">
95
+ <img alt="Opulentyn Logo" src="https://github.com/user-attachments/assets/5fc78032-bff2-4f7e-a174-7d64b22f506d" width="350"/>
96
+ <div>
97
+ <h1>Credit Card OCR</h1>
98
+ <p>We offer <b>on-premises</b> OCR and liveness check solutions available with a <b>perpetual license</b>.</p>
99
+ </div>
100
+ </div>
101
+
102
+ ## 🤝 Talk to us
103
+
104
+ <div style="display: flex; align-items: center;">
105
+ <a href="https://opulentyn.com" target="_blank">
106
+ <img src="https://img.shields.io/badge/Website-https%3A%2F%2Fopulentyn.com-blue?style=flat&logo=google-chrome&logoColor=white" alt="Website">
107
+ </a>
108
+ &nbsp;&nbsp;&nbsp;&nbsp;
109
+ <a href="mailto:support@opulentyn.com">
110
+ <img src="https://img.shields.io/badge/Email-support%40opulentyn.com-blue?style=flat&logo=gmail&logoColor=white" alt="Email">
111
+ </a>
112
+ &nbsp;&nbsp;&nbsp;&nbsp;
113
+ <a href="https://wa.me/13435013587" target="_blank">
114
+ <img src="https://img.shields.io/badge/WhatsApp-%2B13435013587-blue?logo=whatsapp&logoColor=green" alt="WhatsApp">
115
+ </a>
116
+ &nbsp;&nbsp;&nbsp;&nbsp;
117
+ <a href="https://join.slack.com/t/opulentyn/shared_invite/zt-2s230jtbq-dWBs8XUZcrYim~nUqiimSA" target="_blank">
118
+ <img src="https://img.shields.io/badge/Slack-support--sdk-blueviolet?style=flat&logo=slack&logoColor=white" alt="Slack">
119
+ </a>
120
+ </div>
121
+ """
122
+ )
123
+
124
+ with gr.Row():
125
+ with gr.Column():
126
+ image_input = gr.Image(type='pil')
127
+ gr.Examples(['examples/1.jpg', 'examples/2.jpg', 'examples/3.jpg'],
128
+ inputs=image_input)
129
+ process_button = gr.Button("Process")
130
+ with gr.Column():
131
+ with gr.TabItem("Image"):
132
+ image_output = gr.Image(type="pil")
133
+ with gr.TabItem("Json"):
134
+ json_output = gr.JSON()
135
+
136
+ process_button.click(process_image, inputs=[image_input], outputs=[image_output, json_output])
137
+
138
+ gr.HTML('<a href="https://visitorbadge.io/status?path=https%3A%2F%2Fhuggingface.co%2Fspaces%2Fopulentyn%2FLicensePlateRecognition"><img src="https://api.visitorbadge.io/api/combined?path=https%3A%2F%2Fhuggingface.co%2Fspaces%2Fopulentyn%2FLicensePlateRecognition&countColor=%23263759" /></a>')
139
+
140
+ demo.launch(server_name="0.0.0.0", server_port=7860)
examples/1.jpg ADDED
examples/2.jpg ADDED
examples/3.jpg ADDED
install.sh ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/bin/bash
2
+
3
+ sudo cp lib/libopycardenv.so /usr/lib
4
+ sudo cp lib/libtensorflow.so.1.14.0 /usr/lib
5
+ sudo ln -s /usr/lib/libtensorflow.so.1.14.0 /usr/lib/libtensorflow.so.1
6
+ sudo ln -s /usr/lib/libtensorflow.so.1.14.0 /usr/lib/libtensorflow.so
7
+
8
+ sudo cp lib/libtensorflow_framework.so.1.14.0 /usr/lib
9
+ sudo ln -s /usr/lib/libtensorflow_framework.so.1.14.0 /usr/lib/libtensorflow_framework.so.1
10
+ sudo ln -s /usr/lib/libtensorflow_framework.so.1.14.0 /usr/lib/libtensorflow_framework.so
11
+
lib/libopycard.so ADDED
Binary file (143 kB). View file
 
lib/libopycardenv.so ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:7d05d12d34540dded22034918c37a1df0b0c5396a0e460f31292849e17c4a226
3
+ size 3943952
lib/libtensorflow.so.1.14.0 ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:055751c7691dcec4506658d96f02b17632759299534b4ddd2a47627d192b38d7
3
+ size 216546752
lib/libtensorflow_framework.so.1.14.0 ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:b5648d27a4c58a5669d1d3d40326da9aaf414d443dfac7de273ecf3a28a97679
3
+ size 34748520
license.txt ADDED
@@ -0,0 +1 @@
 
 
1
+ gHCbGlNYovccScwbo52dFL6rz9wsgcn0aG1M1TOIGp0yC4Bu3t0CjOzKC9/G5YYh8T1OtWdDVU0YUXNR6bLRJLxP2vd+suclRwzpDdVZ2J0Ab33boUdSJ+23idE9dSjWNMDO4cvaQj7zW7WAYixoMC01SBBTKOinhm7z/rrqyP8=
model/detect.bin ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:c5010fda486f4395d064447ef1c4a806be41c776896e76cb5d80f1f653e85bbc
3
+ size 13253378
model/fp.bin ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:fd5669349ef0ee0278a3444ae31057bf218f6c006699e517813100d3b5959340
3
+ size 230
model/map.bin ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:ea598067f0383fa8e0fb430528d38e4a1a855df8782e04813fbd4d23a31f4a26
3
+ size 199
model/recog.bin ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:f9fb4e913f1c6b574bdeffb0cb498c6be838740548f4d4ef7874ad20a855700d
3
+ size 7907130
opycard.py ADDED
@@ -0,0 +1,27 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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/libopycardenv.so'
7
+ opycardenv = cdll.LoadLibrary(libPath)
8
+
9
+ libPath = os.path.abspath(os.path.dirname(__file__)) + '/lib/libopycard.so'
10
+ opycard = cdll.LoadLibrary(libPath)
11
+
12
+ getHWID = opycard.getHWID
13
+ getHWID.argtypes = []
14
+ getHWID.restype = c_char_p
15
+
16
+ setLicenseKey = opycard.setLicenseKey
17
+ setLicenseKey.argtypes = [c_char_p]
18
+ setLicenseKey.restype = c_int32
19
+
20
+ initSDK = opycard.initSDK
21
+ initSDK.argtypes = [c_char_p]
22
+ initSDK.restype = c_int32
23
+
24
+ processImage = opycard.processImage
25
+ processImage.argtypes = [ndpointer(c_ubyte, flags='C_CONTIGUOUS'), c_int32, c_int32]
26
+ processImage.restype = c_char_p
27
+
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/opycard
4
+ exec python3 demo.py &
5
+ exec python3 app.py