ksvmuralidhar commited on
Commit
f0d53ce
1 Parent(s): 2c6861c

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +155 -0
app.py ADDED
@@ -0,0 +1,155 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import numpy as np
3
+ from requests import get
4
+ import streamlit as st
5
+ import cv2
6
+ from ultralytics import YOLO
7
+ import shutil
8
+ import easyocr
9
+ import imutils
10
+
11
+
12
+ PREDICTION_PATH = os.path.join('.', 'predictions')
13
+
14
+
15
+ @st.cache_resource
16
+ def load_od_model():
17
+ finetuned_model = YOLO('cc_detect_best.pt')
18
+ return finetuned_model
19
+
20
+
21
+ @st.cache_resource
22
+ def load_easyocr():
23
+ reader = easyocr.Reader(['en'])
24
+ return reader
25
+
26
+
27
+ def decode_text(type: str):
28
+ reader = load_easyocr()
29
+ output_crop_path = os.path.join(PREDICTION_PATH, 'predict', 'crops', type)
30
+ ocr_txt = ''
31
+ if os.path.exists(output_crop_path):
32
+ crop_file = os.listdir(output_crop_path)[0]
33
+ crop_img_path = os.path.join(output_crop_path, crop_file)
34
+ crop_img = cv2.imread(crop_img_path)
35
+
36
+ increase = cv2.resize(crop_img, None, fx = 2, fy = 2, interpolation = cv2.INTER_CUBIC)
37
+ if type == 'card_number':
38
+ increase = cv2.resize(crop_img, None, fx = 5, fy = 5, interpolation = cv2.INTER_CUBIC)
39
+
40
+ gray = cv2.cvtColor(increase, cv2.COLOR_BGR2GRAY)
41
+
42
+ value, thresh = cv2.threshold(gray,0, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)
43
+
44
+ kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (2,2))
45
+ opening = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel, iterations=1)
46
+
47
+ # Find contours and remove small noise
48
+ cnts = cv2.findContours(opening, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
49
+ cnts = cnts[0] if len(cnts) == 2 else cnts[1]
50
+ for c in cnts:
51
+ area = cv2.contourArea(c)
52
+ if area < 50:
53
+ cv2.drawContours(opening, [c], -1, 0, -1)
54
+
55
+ # Invert
56
+ result = 255 - opening
57
+ cleaned_image = result
58
+
59
+ crop_ocr = reader.readtext(cleaned_image)
60
+
61
+ cleaned_image = cv2.resize(cleaned_image, None, fx = 0.5, fy = 0.5, interpolation = cv2.INTER_CUBIC)
62
+ if type == 'card_number':
63
+ cleaned_image = cv2.resize(cleaned_image, None, fx = 0.2, fy = 0.2, interpolation = cv2.INTER_CUBIC)
64
+ cv2.imwrite(crop_img_path, cleaned_image)
65
+
66
+
67
+ ocr_txt = ''.join([t for _, t, _ in crop_ocr])
68
+ ocr_txt_conf = np.round(np.mean([p for _, _, p in crop_ocr]), 4)
69
+
70
+ if type == 'card_number':
71
+ ocr_txt = ocr_txt.replace(' ', '')
72
+
73
+ col1, col2 = st.columns(2, gap='small')
74
+ with col1:
75
+ st.markdown(f"<h5>{type.replace('_', ' ').upper()}</h5>", unsafe_allow_html=True)
76
+ st.text(f"{ocr_txt.upper()} ({str(ocr_txt_conf)})")
77
+ with col2:
78
+ st.text(' ')
79
+ if type == 'card_number':
80
+ st.text(' ')
81
+ st.image(crop_img_path)
82
+
83
+
84
+
85
+ def inference(input_image_path: str):
86
+ finetuned_model = load_od_model()
87
+ results = finetuned_model.predict(input_image_path,
88
+ show=False,
89
+ save=True,
90
+ save_crop=True,
91
+ imgsz=640,
92
+ conf=0.6,
93
+ save_txt=True,
94
+ project= PREDICTION_PATH,
95
+ show_labels=True,
96
+ show_conf=True,
97
+ line_width=2,
98
+ exist_ok=True)
99
+
100
+ decode_text('card_number')
101
+ decode_text('holder_name')
102
+ decode_text('exp_date')
103
+
104
+ st.image(os.path.join(PREDICTION_PATH, 'predict', 'input.jpg'))
105
+
106
+
107
+ def files_cleanup(path_: str):
108
+ if os.path.exists(path_):
109
+ os.remove(path_)
110
+ if os.path.exists(PREDICTION_PATH):
111
+ shutil.rmtree(PREDICTION_PATH)
112
+
113
+
114
+ @st.cache_resource
115
+ def get_upload_path():
116
+ upload_file_path = os.path.join('.', 'uploads')
117
+ if not os.path.exists(upload_file_path):
118
+ os.makedirs(upload_file_path)
119
+ upload_filename = "input.jpg"
120
+ upload_file_path = os.path.join(upload_file_path, upload_filename)
121
+ return upload_file_path
122
+
123
+
124
+ def process_input_image(img_url):
125
+ upload_file_path = get_upload_path()
126
+ headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/102.0.0.0 Safari/537.36'}
127
+ r = get(img_url, headers=headers)
128
+ arr = np.frombuffer(r.content, np.uint8)
129
+ input_image = cv2.imdecode(arr, cv2.IMREAD_UNCHANGED)
130
+ input_image = cv2.cvtColor(input_image, cv2.COLOR_BGR2RGB)
131
+ input_image = cv2.resize(input_image, (640, 640))
132
+ cv2.imwrite(upload_file_path, cv2.cvtColor(input_image, cv2.COLOR_RGB2BGR))
133
+ return upload_file_path
134
+
135
+
136
+ try:
137
+ files_cleanup(get_upload_path())
138
+ st.markdown("<h3>Credit Card Detection</h3>", unsafe_allow_html=True)
139
+ desc = '''YOLOv8 is fine-tuned to detect credit card number, holder's name and expiry date. Dataset used to fine-tune YOLOv8
140
+ can be found <a href="https://universe.roboflow.com/credit-cards-detection/credit_card_detect-wjmlc/dataset/2" target="_blank">
141
+ here</a>. The detected objects are cropped, processed and passed as inputs to EasyOCR for text recognition.
142
+ '''
143
+ st.markdown(desc, unsafe_allow_html=True)
144
+ img_url = st.text_input("Paste the image URL of a credit card:", "")
145
+ placeholder = st.empty()
146
+ if img_url:
147
+ placeholder.empty()
148
+ img_path = process_input_image(img_url)
149
+ inference(img_path)
150
+ files_cleanup(get_upload_path())
151
+
152
+
153
+ except Exception as e:
154
+ files_cleanup(get_upload_path())
155
+ st.error(f'An unexpected error occured: \n{e}')