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