Vahe commited on
Commit
5d2ed09
·
1 Parent(s): 4a0126b
app.py ADDED
@@ -0,0 +1,85 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ import cv2
3
+ import numpy as np
4
+ from PIL import Image, ImageDraw
5
+ # import imutils
6
+ # import easyocr
7
+ # import os
8
+ # import pathlib
9
+ # import platform
10
+ # from xyxy_converter import yolov5_to_image_coordinates
11
+ # import shutil
12
+ from extractor import get_card_xy, get_digit
13
+
14
+ # system_platform = platform.system()
15
+ # if system_platform == 'Windows': pathlib.PosixPath = pathlib.WindowsPath
16
+
17
+ # CUR_DIR = os.getcwd()
18
+ # YOLO_PATH = f"{CUR_DIR}/yolov5"
19
+ # MODEL_PATH = "runs/train/exp/weights/best.pt"
20
+
21
+ def main():
22
+ st.title("Card number extractor")
23
+
24
+ # Use st.camera to capture images from the user's camera
25
+ img_file_buffer = st.camera_input(label='Please, take a photo of a card')
26
+
27
+ # try:
28
+ # image = Image.open(img_file_buffer)
29
+ # except:
30
+ # st.write('No shot detected')
31
+
32
+ # Check if an image is captured
33
+ if img_file_buffer is not None:
34
+ # Convert the image to a NumPy array
35
+ image = Image.open(img_file_buffer)
36
+ image_np = np.array(image)
37
+ resized_image = cv2.resize(image_np, (128, 128))
38
+ resized_image = resized_image.astype(np.uint8)
39
+ resized_image = cv2.cvtColor(resized_image, cv2.COLOR_BGR2RGB)
40
+ cv2.imwrite('card_image.jpg', resized_image)
41
+
42
+ # original_img = cv2.imread('card_image.jpg')
43
+ gray = cv2.cvtColor(resized_image, cv2.COLOR_BGR2GRAY)
44
+
45
+ x1, y1, x2, y2, card_confidence = get_card_xy(
46
+ model_path='credit_card_number_detector.tflite',
47
+ image_path='card_image.jpg'
48
+ )
49
+
50
+ st.write(card_confidence)
51
+
52
+ if card_confidence == 0:
53
+ display_text = "A card is not detected in the image!!!"
54
+ st.image('card_image.jpg', caption=f"{display_text}", use_column_width=True)
55
+ else:
56
+ cropped_image = gray[y1:y2, x1:x2]
57
+ # cropped_image = resized_image[y1:y2, x1:x2]
58
+ cropped_image = cv2.resize(cropped_image, (128, 128))
59
+ cv2.imwrite('card_number_image.jpg', cropped_image)
60
+
61
+ extracted_digit = get_digit(
62
+ model_path="card_number_extractor.tflite",
63
+ image_path='card_number_image.jpg',
64
+ threshold=0.4
65
+ )
66
+
67
+ display_text = f'Here is the zoomed card number: {extracted_digit}'
68
+ st.image('card_number_image.jpg', caption=f"{display_text}", use_column_width=True)
69
+
70
+ image = Image.open('card_image.jpg')
71
+ image_resized = image.resize((640, 640))
72
+ draw = ImageDraw.Draw(image_resized)
73
+ draw.rectangle([x1, y1, x2, y2], outline="red", width=2)
74
+ class_name = 'card'
75
+ text = f"Class: {class_name}, Confidence: {card_confidence:.2f}"
76
+ draw.text((x1, y1), text, fill="red")
77
+ # Saving Images
78
+ image_resized.save('card_highlighted_image.jpg')
79
+ display_text = 'Here is the card on the image.'
80
+ st.image('card_highlighted_image.jpg', caption=f"{display_text}", use_column_width=True)
81
+
82
+ st.session_state.pop("card")
83
+
84
+ if __name__ == "__main__":
85
+ main()
card_number_extractor.tflite ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:040573544cc95efd2efda024d4d5d526e18b1ec31afd894be877b1ca91627d37
3
+ size 12102383
credit_card_number_detector.tflite ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:ce560776ea2d978fb398e2e80add8f8ff25dafecd299c989e873345971024aa0
3
+ size 12104152
extractor.py ADDED
@@ -0,0 +1,159 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import tensorflow as tf
2
+ import numpy as np
3
+ from PIL import Image
4
+ import cv2
5
+
6
+ def get_card_xy(model_path, image_path):
7
+ #model_path = 'odo_detector.tflite'
8
+ interpreter = tf.lite.Interpreter(model_path=model_path)
9
+ interpreter.allocate_tensors()
10
+
11
+ input_details = interpreter.get_input_details()
12
+ output_details = interpreter.get_output_details()
13
+
14
+ # Obtain the height and width of the corresponding image from the input tensor
15
+ image_height = input_details[0]['shape'][1] # 640
16
+ image_width = input_details[0]['shape'][2] # 640
17
+
18
+ # Image Preparation
19
+ # image_name = 'car.jpg'
20
+ image = Image.open(image_path)
21
+ image_resized = image.resize((image_width, image_height)) # Resize the image to the corresponding size of the input tensor and store it in a new variable
22
+
23
+ image_np = np.array(image_resized) #
24
+ image_np = np.true_divide(image_np, 255, dtype=np.float32)
25
+ image_np = image_np[np.newaxis, :]
26
+
27
+ # inference
28
+ interpreter.set_tensor(input_details[0]['index'], image_np)
29
+ interpreter.invoke()
30
+
31
+ # Obtaining output results
32
+ output = interpreter.get_tensor(output_details[0]['index'])
33
+ output = output[0]
34
+ output = output.T
35
+
36
+ boxes_xywh = output[:, :4] #Get coordinates of bounding box, first 4 columns of output tensor
37
+ scores = output[:, 4]#np.max(output[..., 5:], axis=1) #Get score value, 5th column of output tensor
38
+ classes = np.zeros(len(scores))#np.argmax(output[..., 5:], axis=1) # Get the class value, get the 6th and subsequent columns of the output tensor, and store the largest value in the output tensor.
39
+
40
+ # Threshold Setting
41
+ # threshold = 0.7
42
+ final_score = 0
43
+ x_center, y_center, width, height = 0, 0, 0, 0
44
+ class_name = 'card_number'
45
+
46
+ # Bounding boxes, scores, and classes are drawn on the image
47
+ # draw = ImageDraw.Draw(image_resized)
48
+
49
+ for box, score, cls in zip(boxes_xywh, scores, classes):
50
+ if score >= final_score:
51
+ x_center, y_center, width, height = box
52
+ final_score = score
53
+ class_name = cls
54
+ else:
55
+ pass
56
+
57
+ x1 = int((x_center - width / 2) * image_width)
58
+ y1 = int((y_center - height / 2) * image_height)
59
+ x2 = int((x_center + width / 2) * image_width)
60
+ y2 = int((y_center + height / 2) * image_height)
61
+
62
+ # draw.rectangle([x1, y1, x2, y2], outline="red", width=2)
63
+ # text = f"Class: {class_name}, Score: {final_score:.2f}"
64
+ # draw.text((x1, y1), text, fill="red")
65
+
66
+ # Saving Images
67
+ # image_resized.save('test_img.jpg')
68
+
69
+ return x1, y1, x2, y2, final_score
70
+
71
+ def get_digit(model_path, image_path, threshold=0.5):
72
+
73
+ interpreter = tf.lite.Interpreter(model_path=model_path)
74
+ interpreter.allocate_tensors()
75
+
76
+ input_details = interpreter.get_input_details()
77
+ output_details = interpreter.get_output_details()
78
+
79
+ # Obtain the height and width of the corresponding image from the input tensor
80
+ image_height = input_details[0]['shape'][1] # 640
81
+ image_width = input_details[0]['shape'][2] # 640
82
+
83
+ # Image Preparation
84
+ # image_name = 'car.jpg'
85
+ # image = Image.open(image_path2)
86
+ # image_resized = image.resize((image_width, image_height)) # Resize the image to the corresponding size of the input tensor and store it in a new variable
87
+ image = cv2.imread(image_path)
88
+ # image_resized = np.resize(image, (image_width, image_height, 3))
89
+
90
+ image_np = np.array(image) #
91
+ image_np = np.true_divide(image_np, 255, dtype=np.float32)
92
+ image_np = image_np[np.newaxis, :]
93
+
94
+ # inference
95
+ interpreter.set_tensor(input_details[0]['index'], image_np)
96
+ interpreter.invoke()
97
+
98
+ # Obtaining output results
99
+ output = interpreter.get_tensor(output_details[0]['index'])
100
+ output = output[0]
101
+ output = output.T
102
+
103
+ boxes_xywh = output[:, :4] #Get coordinates of bounding box, first 4 columns of output tensor
104
+ scores = np.max(output[:, 4:], axis=1) #Get score value, 5th column of output tensor
105
+ classes = np.argmax(output[:, 4:], axis=1) # Get the class value, get the 6th and subsequent columns of the output tensor, and store the largest value in the output tensor.
106
+
107
+ pred_list = []
108
+
109
+ prob_threshold = threshold
110
+
111
+ for box, score, cls in zip(boxes_xywh, scores, classes):
112
+
113
+ if score < prob_threshold:
114
+ continue
115
+
116
+ x_center, y_center, width, height = box
117
+ x1 = int((x_center - width / 2) * image_width)
118
+ y1 = int((y_center - height / 2) * image_height)
119
+ x2 = int((x_center + width / 2) * image_width)
120
+ y2 = int((y_center + height / 2) * image_height)
121
+
122
+ pred_list.append((x1, x2, cls, score))
123
+
124
+ pred_list = sorted(pred_list, key=lambda x: x[0])
125
+
126
+ num_list = []
127
+
128
+ temp_pred_list =[]
129
+
130
+ x_prev = 0
131
+
132
+ x_diff = min([elem[1] - elem[0] for elem in pred_list]) - 10
133
+
134
+ for idx, pred in enumerate(pred_list):
135
+
136
+ if idx == 0:
137
+ temp_pred_list.append(pred)
138
+ x_prev = pred[0]
139
+ elif idx == len(pred_list) - 1:
140
+ temp_final_num = sorted(temp_pred_list, key=lambda x: x[-1], reverse=True)[0]
141
+ num_list.append(temp_final_num)
142
+ elif pred[0] - x_prev < x_diff:
143
+ temp_pred_list.append(pred)
144
+ x_prev = pred[0]
145
+ else:
146
+ temp_final_num = sorted(temp_pred_list, key=lambda x: x[-1], reverse=True)[0]
147
+ num_list.append(temp_final_num)
148
+ temp_pred_list = []
149
+ x_prev = pred[0]
150
+ temp_pred_list.append(pred)
151
+
152
+ sorted_number_list = sorted(num_list, key=lambda x: x[0])
153
+ # sorted_number_list = sorted(sorted_number_list, reverse=True, key= lambda x: x[-1])
154
+ # output_digit = float(''.join([str(int(i[2])) if i[2]!=10 else '.' for i in sorted_number_list]))
155
+ output_digit = float(''.join([str(int(i[2])) if i[2]!=10 else '.' for i in sorted_number_list]))
156
+ # output_digit = ''.join([str(int(i[2])) if i[2]!=10 else '.' for i in sorted_number_list[:10]])
157
+
158
+ return output_digit
159
+
requirements.txt.txt ADDED
@@ -0,0 +1,70 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ absl-py==2.1.0
2
+ altair==5.2.0
3
+ astunparse==1.6.3
4
+ attrs==23.2.0
5
+ blinker==1.7.0
6
+ cachetools==5.3.2
7
+ certifi==2023.11.17
8
+ charset-normalizer==3.3.2
9
+ click==8.1.7
10
+ colorama==0.4.6
11
+ flatbuffers==23.5.26
12
+ gast==0.5.4
13
+ gitdb==4.0.11
14
+ GitPython==3.1.41
15
+ google-auth==2.26.2
16
+ google-auth-oauthlib==1.2.0
17
+ google-pasta==0.2.0
18
+ grpcio==1.60.0
19
+ h5py==3.10.0
20
+ idna==3.6
21
+ importlib-metadata==7.0.1
22
+ Jinja2==3.1.3
23
+ jsonschema==4.21.1
24
+ jsonschema-specifications==2023.12.1
25
+ keras==2.15.0
26
+ libclang==16.0.6
27
+ Markdown==3.5.2
28
+ markdown-it-py==3.0.0
29
+ MarkupSafe==2.1.4
30
+ mdurl==0.1.2
31
+ ml-dtypes==0.2.0
32
+ numpy==1.26.3
33
+ oauthlib==3.2.2
34
+ opencv-python==4.9.0.80
35
+ opt-einsum==3.3.0
36
+ packaging==23.2
37
+ pandas==2.2.0
38
+ pillow==10.2.0
39
+ protobuf==4.23.4
40
+ pyarrow==15.0.0
41
+ pyasn1==0.5.1
42
+ pyasn1-modules==0.3.0
43
+ pydeck==0.8.1b0
44
+ Pygments==2.17.2
45
+ python-dateutil==2.8.2
46
+ pytz==2023.3.post1
47
+ referencing==0.32.1
48
+ requests==2.31.0
49
+ requests-oauthlib==1.3.1
50
+ rich==13.7.0
51
+ rpds-py==0.17.1
52
+ rsa==4.9
53
+ six==1.16.0
54
+ smmap==5.0.1
55
+ streamlit==1.30.0
56
+ tenacity==8.2.3
57
+ tensorflow==2.15.0
58
+ termcolor==2.4.0
59
+ toml==0.10.2
60
+ toolz==0.12.0
61
+ tornado==6.4
62
+ typing_extensions==4.9.0
63
+ tzdata==2023.4
64
+ tzlocal==5.2
65
+ urllib3==2.1.0
66
+ validators==0.22.0
67
+ watchdog==3.0.0
68
+ Werkzeug==3.0.1
69
+ wrapt==1.14.1
70
+ zipp==3.17.0