Kartik13 commited on
Commit
b742bb1
·
verified ·
1 Parent(s): 42a8f09

Upload app.py

Browse files
Files changed (1) hide show
  1. app.py +208 -0
app.py ADDED
@@ -0,0 +1,208 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ from PIL import Image
3
+ import onnx
4
+ import easyocr
5
+ import os
6
+ import cv2
7
+ import numpy as np
8
+ import pandas as pd
9
+ import tensorflow as tf
10
+ import pytesseract as pt
11
+ import plotly.express as px
12
+ import matplotlib.pyplot as plt
13
+ import xml.etree.ElementTree as xet
14
+ import pytesseract
15
+ from transformers import TrOCRProcessor, VisionEncoderDecoderModel
16
+ from PIL import Image
17
+ import torch
18
+
19
+ from glob import glob
20
+ from skimage import io
21
+ from shutil import copy
22
+ from tensorflow.keras.models import Model
23
+ from tensorflow.keras.callbacks import TensorBoard
24
+ from sklearn.model_selection import train_test_split
25
+ from tensorflow.keras.applications import InceptionResNetV2
26
+ from tensorflow.keras.layers import Dense, Dropout, Flatten, Input
27
+ from tensorflow.keras.preprocessing.image import load_img, img_to_array
28
+
29
+ #Define the Image height and width
30
+ INPUT_WIDTH = 640
31
+ INPUT_HEIGHT = 640
32
+
33
+ # load YOLO model
34
+ net = cv2.dnn.readNetFromONNX('/Users/kartikrathi/Documents/ANPR_Project/yolov5/runs/train/Model/weights/best.onnx')
35
+ net.setPreferableBackend(cv2.dnn.DNN_BACKEND_OPENCV)
36
+ net.setPreferableTarget(cv2.dnn.DNN_TARGET_CPU)
37
+
38
+
39
+ def get_detections(img, net):
40
+ # 1. CONVERT IMAGE TO YOLO FORMAT
41
+ image = np.array(img)
42
+
43
+ # Ensure the image has three channels (remove alpha channel if present)
44
+ if image.shape[2] == 4:
45
+ image = image[:, :, :3]
46
+
47
+ row, col, _ = image.shape # Extract row, column, and channels of image
48
+
49
+ max_rc = max(row, col) # Calculate max number of rows and cols
50
+ input_image = np.zeros((max_rc, max_rc, 3), dtype=np.uint8)
51
+ input_image[0:row, 0:col, :] = image # Assign values to the channels
52
+
53
+ # 2. GET PREDICTION FROM YOLO MODEL
54
+ blob = cv2.dnn.blobFromImage(input_image, 1/255.0, (INPUT_WIDTH, INPUT_HEIGHT), swapRB=True, crop=False)
55
+ net.setInput(blob)
56
+ preds = net.forward()
57
+ detections = preds[0]
58
+
59
+ return input_image, detections
60
+
61
+
62
+ def non_maximum_supression(input_image,detections):
63
+
64
+ '''
65
+ This function takes the preprocessed image (input_image) and the raw detections obtained from the YOLO model
66
+ (detections) and performs non-maximum suppression (NMS) to filter out redundant detections.
67
+ '''
68
+
69
+ # 3. FILTER DETECTIONS BASED ON CONFIDENCE AND PROBABILIY SCORE
70
+
71
+ # center x, center y, w , h, conf, proba
72
+ boxes = []
73
+ confidences = []
74
+
75
+ image_w, image_h = input_image.shape[:2]
76
+ x_factor = image_w/INPUT_WIDTH #x_factor and y_factor are scaling factors to adjust bounding box coordinates based on the original image dimensions.
77
+ y_factor = image_h/INPUT_HEIGHT
78
+
79
+
80
+ #The confidence score indicates how sure the model is that the box contains an object and also how accurate it thinks the box is that predicts
81
+ for i in range(len(detections)):
82
+ row = detections[i]
83
+ confidence = row[4] # confidence of detecting license plate
84
+ if confidence > 0.4:
85
+ class_score = row[5] # probability score of license plate
86
+ if class_score > 0.25:
87
+ cx, cy , w, h = row[0:4]
88
+
89
+ left = int((cx - 0.5*w)*x_factor)
90
+ top = int((cy-0.5*h)*y_factor)
91
+ width = int(w*x_factor)
92
+ height = int(h*y_factor)
93
+ box = np.array([left,top,width,height])
94
+
95
+ confidences.append(confidence)
96
+ boxes.append(box)
97
+
98
+ # CLEAN
99
+ boxes_np = np.array(boxes).tolist()
100
+ confidences_np = np.array(confidences).tolist()
101
+
102
+ # NMS
103
+ index = cv2.dnn.NMSBoxes(boxes_np,confidences_np,0.25,0.45)
104
+
105
+ return boxes_np, confidences_np, index
106
+
107
+ def drawings(image, boxes_np, confidences_np, index):
108
+ # Drawings
109
+ image_draw = image.copy()
110
+ image_draw = np.array(image_draw)# Create a copy to avoid modifying the original image
111
+ for ind in index:
112
+ x, y, w, h = boxes_np[ind]
113
+ bb_conf = confidences_np[ind]
114
+ conf_text = 'plate: {:.0f}%'.format(bb_conf * 100)
115
+
116
+ cv2.rectangle(image_draw, (int(x), int(y)), (int(x+w), int(y+h)), (255, 0, 255), 2)
117
+ cv2.rectangle(image_draw, (int(x), int(y-30)), (int(x+w), int(y)), (255, 0, 255), -1)
118
+ cv2.rectangle(image_draw, (int(x), int(y+h)), (int(x+w), int(y+h+25)), (0, 0, 0), -1)
119
+
120
+ cv2.putText(image_draw, conf_text, (int(x), int(y-10)), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (255, 255, 255), 1)
121
+
122
+ return image_draw
123
+
124
+ def yolo_predictions(img, net):
125
+ # Step 1: Get detections
126
+ input_image, detections = get_detections(img, net)
127
+
128
+ # Step 2: Non-Maximum Suppression
129
+ boxes_np, confidences_np, index = non_maximum_supression(input_image, detections)
130
+
131
+ # Step 3: Drawings
132
+ result_img = drawings(img, boxes_np, confidences_np, index)
133
+
134
+ # Extract bounding box coordinates
135
+ bounding_box_coords = [boxes_np[i] for i in index]
136
+
137
+ return result_img, bounding_box_coords
138
+
139
+ #Crop the image
140
+ def crop_image(img, x, y, width, height):
141
+
142
+ # Convert the image array to a Pillow Image object
143
+ pil_img = Image.fromarray(img)
144
+
145
+ # Crop the image using the provided coordinates
146
+ cropped_img = pil_img.crop((x, y, x + width, y + height))
147
+
148
+ # Convert the cropped image back to a NumPy array
149
+ cropped_img_array = np.array(cropped_img)
150
+
151
+ return cropped_img_array
152
+
153
+ def tr_ocr_image_from_array(image_array):
154
+ processor = TrOCRProcessor.from_pretrained("microsoft/trocr-large-printed")
155
+ model = VisionEncoderDecoderModel.from_pretrained("microsoft/trocr-large-printed")
156
+
157
+ def tr_ocr_image(src_img):
158
+ pixel_values = processor(images=src_img, return_tensors="pt").pixel_values
159
+ generated_ids = model.generate(pixel_values)
160
+ return processor.batch_decode(generated_ids, skip_special_tokens=True)[0]
161
+
162
+ # Convert the image array to a PIL image
163
+ img = Image.fromarray(image_array).convert("RGB")
164
+
165
+ # Perform OCR on the image
166
+ return tr_ocr_image(img)
167
+
168
+ def main():
169
+ st.title("Automatic Number Plate Recognition (ANPR) App")
170
+ st.write("Upload an image and let the app detect the vehicle number plate.")
171
+
172
+ uploaded_image = st.file_uploader("Choose an image ", type=["jpg", "jpeg", "png"])
173
+
174
+ if uploaded_image is not None:
175
+ # Display the uploaded image
176
+ st.image(uploaded_image, caption="Uploaded Image", use_column_width=True)
177
+
178
+ # Convert the uploaded image to a PIL Image
179
+ image = Image.open(uploaded_image)
180
+
181
+ # Detect the number plate
182
+ number_plate_img, coords = yolo_predictions(image, net)
183
+
184
+ # Display the detected number plate image
185
+ st.image(number_plate_img, caption="Detected Number Plate", use_column_width=True)
186
+
187
+ for box in coords:
188
+ x, y, width, height = box
189
+
190
+ # Crop the image
191
+ cropped_image = crop_image(np.array(number_plate_img), x, y, width, height)
192
+
193
+ # Display the coordinates
194
+ st.write("Detected Number Plate Coordinates:", coords)
195
+
196
+ # Display the cropped image
197
+ st.image(cropped_image, caption="Detected Number Plate", use_column_width=True)
198
+
199
+ #display the extracted number from number plate
200
+ cropped_image = np.array(cropped_image) # Replace ... with your actual image array
201
+ extracted_text = tr_ocr_image_from_array(cropped_image)
202
+
203
+ st.write("Extracted text: ")
204
+ st.text(extracted_text)
205
+
206
+
207
+ if __name__ == "__main__":
208
+ main()