Spaces:
Sleeping
Sleeping
| import streamlit as st | |
| from streamlit_image_select import image_select | |
| import tensorflow as tf | |
| import datetime | |
| from pytz import timezone | |
| import os | |
| import pandas as pd | |
| import numpy as np | |
| import cv2 | |
| from PIL import Image | |
| # trained model files and paths | |
| files = { | |
| "label_map_ssd" : os.path.join('eported_models','ssd_mobilnet_numberplate_region_detection','label_map.pbtxt'), | |
| "label_map_efficientdet" : os.path.join('eported_models','efficientdet_d0_ocr_numberplate','label_map.pbtxt') | |
| } | |
| paths = { | |
| "saved_model_path_ssd" : os.path.join('eported_models','ssd_mobilnet_numberplate_region_detection','saved_model'), | |
| "saved_model_path_efficientdet" : os.path.join('eported_models','efficientdet_d0_ocr_numberplate','saved_model') | |
| } | |
| def read_label_map(label_map_path): | |
| item_id = None | |
| item_name = None | |
| items = {} | |
| with open(label_map_path, "r") as file: | |
| for line in file: | |
| line.replace(" ", "") | |
| if line == "item{": | |
| pass | |
| elif line == "}": | |
| pass | |
| elif "id" in line: | |
| item_id = int(line.split(":", 1)[1].strip()) | |
| elif "name" in line: | |
| item_name = {line.split(":")[0].replace("\"", " ").strip() : line.split(":")[1].replace("'", '').strip()} | |
| if item_id is not None and item_name is not None: | |
| items[item_id] = item_name | |
| item_id = None | |
| item_name = None | |
| return items | |
| #load model | |
| def cache_model(path1, path2): | |
| model1 = tf.saved_model.load(path1) | |
| model2 = tf.saved_model.load(path2) | |
| return (model1, model2) | |
| detect_fn_ssd, detect_fn_efficientdet = cache_model(paths["saved_model_path_ssd"], paths["saved_model_path_efficientdet"]) | |
| # Creating category index | |
| category_index_ssd = read_label_map(files["label_map_ssd"]) | |
| category_index_efficientdet = read_label_map(files["label_map_efficientdet"]) | |
| def image_resize_with_padding(image): | |
| image = np.array(image) | |
| image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) | |
| old_size = image.shape[:2] # old_size is in (height, width) format | |
| if max(old_size) > 256: | |
| desired_size = 512 | |
| else: | |
| desired_size = 256 | |
| ratio = float(desired_size)/max(old_size) | |
| new_size = tuple([int(x*ratio) for x in old_size]) | |
| # resize the image | |
| resized = cv2.resize(image, (new_size[1],new_size[0])) | |
| delta_w = desired_size - new_size[1] | |
| delta_h = desired_size - new_size[0] | |
| top, bottom = delta_h//2, delta_h-(delta_h//2) | |
| left, right = delta_w//2, delta_w-(delta_w//2) | |
| # print(top,bottom,left,right) | |
| color = [255, 255, 255] | |
| new_im = cv2.copyMakeBorder(resized, top, bottom, left, right, cv2.BORDER_CONSTANT,value=color) | |
| return new_im | |
| def image_resize(image): | |
| image = np.array(image) | |
| image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) | |
| old_size = image.shape[:2] # old_size is in (height, width) format | |
| print(old_size) | |
| if max(old_size) >= 1080: | |
| desired_size = 1080 | |
| else: | |
| desired_size = max(old_size) | |
| if desired_size == 1080: | |
| ratio = float(desired_size)/ max(old_size) | |
| new_size = tuple([int(x*ratio) for x in old_size]) | |
| resized = cv2.resize(image, (new_size[1],new_size[0])) | |
| if new_size[0] == 1080: | |
| height = 1080 | |
| width = 810 | |
| else: | |
| height = 810 | |
| width = 1080 | |
| delta_w = width - new_size[1] | |
| delta_h = height - new_size[0] | |
| top, bottom = delta_h//2, delta_h-(delta_h//2) | |
| left, right = delta_w//2, delta_w-(delta_w//2) | |
| # print(top,bottom,left,right) | |
| color = [255, 255, 255] | |
| image = cv2.copyMakeBorder(resized, top, bottom, left, right, cv2.BORDER_CONSTANT,value=color) | |
| image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) | |
| return image | |
| def ExtractBBoxes(bboxes, bclasses, bscores, im_width, im_height, threshold, category_index): | |
| bbox = [] | |
| class_labels = [] | |
| for idx in range(len(bboxes)): | |
| if bscores[idx] >= threshold: | |
| y_min = int(bboxes[idx][0] * im_height) | |
| x_min = int(bboxes[idx][1] * im_width) | |
| y_max = int(bboxes[idx][2] * im_height) | |
| x_max = int(bboxes[idx][3] * im_width) | |
| class_label = category_index[int(bclasses[idx])]['name'] | |
| class_labels.append(class_label) | |
| bbox.append([x_min, y_min, x_max, y_max, class_label, float(bscores[idx])]) | |
| return (bbox, class_labels) | |
| def ocr_predict(img,threshold): | |
| img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) | |
| image_np = tf.convert_to_tensor(img, dtype=tf.uint8) | |
| input_tensor = np.expand_dims(image_np, 0) | |
| image_height, image_width, _ = image_np.shape | |
| detections = detect_fn_efficientdet(input_tensor) | |
| bboxes = detections['detection_boxes'][0].numpy() | |
| bclasses = detections['detection_classes'][0].numpy().astype(np.int32) | |
| bscores = detections['detection_scores'][0].numpy() | |
| det_boxes, class_labels = ExtractBBoxes(bboxes, bclasses, bscores, image_width, image_height, threshold, category_index_efficientdet) | |
| output = [] | |
| for detection in det_boxes: | |
| x_min, y_min, x_max, y_max, label, score = detection[0], detection[1], detection[2], detection[3], detection[4], round(detection[5]) | |
| output.append((label, int(x_min*image_width), int(y_min*image_height), | |
| int(x_max*image_width), int(y_max*image_height), score)) | |
| df = pd.DataFrame(output, columns = ['label','xmin','ymin','xmax','ymax', 'score']) | |
| df_up = df[df.ymin < (df.ymin.min()*1.2)].sort_values(by = ['xmin']) | |
| df_down = df[df.ymin > (df.ymin.min()*1.2)].sort_values(by = ['xmin']) | |
| df = pd.concat([df_up,df_down]) | |
| vehicle_number = "".join(df["label"]) | |
| current_date_time = datetime.datetime.now() | |
| now_asia = current_date_time.astimezone(timezone('Asia/Kolkata')) | |
| day = now_asia.strftime("%A") | |
| date = now_asia.strftime("%d/%m/%Y") | |
| time = now_asia.strftime("%I:%M:%S %p") | |
| data = [(vehicle_number,day,date,time)] | |
| return (data) | |
| def predict(img,threshold): | |
| image_np = np.array(img) | |
| img = cv2.cvtColor(image_np, cv2.COLOR_BGR2RGB) | |
| image = tf.convert_to_tensor(img, dtype=tf.uint8) | |
| input_tensor = np.expand_dims(image, 0) | |
| # image = tf.image.decode_image(open(file, 'rb').read(), channels=3) | |
| # img = cv2.imread(file) | |
| image_height, image_width, _ = image.shape | |
| # input_tensor = np.expand_dims(image, 0) | |
| detections = detect_fn_ssd(input_tensor) | |
| bboxes = detections['detection_boxes'][0].numpy() | |
| bclasses = detections['detection_classes'][0].numpy().astype(np.int32) | |
| bscores = detections['detection_scores'][0].numpy() | |
| det_boxes, class_labels = ExtractBBoxes(bboxes, bclasses, bscores, image_width, image_height, threshold, category_index_ssd) | |
| output = [] | |
| for detection in det_boxes: | |
| x_min, y_min, x_max, y_max, label, score = detection[0], detection[1], detection[2], detection[3], detection[4], round(detection[5]) | |
| output.append((label, x_min, y_min, x_max, y_max, score)) | |
| image_np_with_detections = image_np.copy() | |
| data_list = [] | |
| for l, x_min, y_min, x_max, y_max, score in output: | |
| array = cv2.cvtColor(np.array(img), cv2.COLOR_RGB2BGR) | |
| image = Image.fromarray(array) | |
| cropped_img = image.crop((x_min, y_min, x_max, y_max)) | |
| input_ocr_image = image_resize_with_padding(cropped_img) | |
| data = ocr_predict(input_ocr_image,threshold) | |
| data_list.append(data) | |
| for l, x_min, y_min, x_max, y_max, score in output: | |
| x1 = x_min | |
| y1 = y_min | |
| x2 = x_max | |
| y2 = y_max | |
| # For bounding box | |
| color = (0,255,0) | |
| img = cv2.rectangle(img, (x1, y1), (x2, y2),color, 2) | |
| label = f"{l} : {round(score,2)}" | |
| text_color = (0,0,255) | |
| # For the text background | |
| # Finds space required by the text so that we can put a background with that amount of width. | |
| (w, h), _ = cv2.getTextSize( | |
| label, cv2.FONT_HERSHEY_SIMPLEX, 0.6, 1) | |
| # Prints the text. | |
| img = cv2.rectangle(img, (x1, y1 - 20), (x1 + w, y1), color, -1) | |
| img = cv2.putText(img, label, (x1, y1 - 5), | |
| cv2.FONT_HERSHEY_SIMPLEX, 0.6, text_color, 1) | |
| # plt.imshow(img) | |
| im_rgb = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) | |
| return (im_rgb, data_list) | |
| st.write(""" | |
| # Automated Number Plate Recognition | |
| """ | |
| ) | |
| st.write(""" | |
| **For full code implementation and sub modules please visit the [Github link](https://github.com/gourav300/Automated-Number-plate-Recognition-for-Indian-Vehicles)** | |
| """) | |
| ### load file | |
| uploaded_file = st.file_uploader("Upload an image file for a vehicle with standard number plate", type=["jpg", "png", "jpeg"]) | |
| st.write("Note -: if you have uploaded an image please click X to enable below images") | |
| test_img = image_select( | |
| label='''Select an image to get number plate data''', | |
| images=[ | |
| "test_images/test1.jpg", | |
| "test_images/test2.png", | |
| "test_images/test3.png", | |
| "test_images/test4.jpg", | |
| "test_images/test5.jpg", | |
| "test_images/test6.jpg", | |
| "test_images/test7.jpg", | |
| "test_images/test8.jpg", | |
| ]) | |
| if uploaded_file is not None: | |
| image = Image.open(uploaded_file) | |
| scale_image = image_resize(image) | |
| img, data = predict(scale_image, 0.6) | |
| # image = Image.open(uploaded_file) | |
| st.image(img, use_column_width=True) | |
| st.write(f''' | |
| Vehicle details : | |
| {data} | |
| ''') | |
| else: | |
| image = Image.open(test_img) | |
| img, data = predict(image, 0.6) | |
| st.image(img, use_column_width=True) | |
| st.write(f''' | |
| Vehicle details : | |
| {data} | |
| ''') |