|
import streamlit as st |
|
import streamlit as st |
|
import argparse |
|
import io |
|
from io import BytesIO |
|
from PIL import ImageOps, Image |
|
import os |
|
import cv2 |
|
import random |
|
import warnings |
|
import numpy as np |
|
import pandas as pd |
|
import seaborn as sns |
|
from tqdm import tqdm |
|
from ultralytics import YOLO |
|
from termcolor import colored |
|
import matplotlib.pyplot as plt |
|
|
|
st.set_page_config( |
|
page_title="Auto NPR", |
|
page_icon="β¨", |
|
layout="centered", |
|
initial_sidebar_state="expanded", |
|
) |
|
|
|
top_image = Image.open('banner_top.png') |
|
bottom_image = Image.open('banner_bottom.png') |
|
main_image = Image.open('main_banner.png') |
|
|
|
upload_path = "" |
|
download_path = "" |
|
|
|
st.image(main_image,use_column_width='auto') |
|
st.title(' Automatic Number Plate Recognition ππ') |
|
st.sidebar.image(top_image,use_column_width='auto') |
|
st.sidebar.header('Input π ') |
|
selected_type = st.sidebar.selectbox('Please select an activity type π', ["Upload Image", "Live Video Feed"]) |
|
st.sidebar.image(bottom_image,use_column_width='auto') |
|
|
|
|
|
best_model_plate = YOLO('best.pt') |
|
best_model_digits = YOLO('best2.pt') |
|
|
|
def Detect_Plate(img): |
|
''' |
|
Predict on a car image and return result folder and predicted image path. |
|
''' |
|
result1 = best_model_plate.predict([img], save=True, iou=0.7) |
|
|
|
|
|
result_path1 = result1[0].save_dir |
|
pred1_path = os.path.join(result_path1, os.listdir(result_path1)[-1]) |
|
return result1, pred1_path |
|
|
|
def Detect_Digits(img2) : |
|
''' |
|
Predict on a croped plate and return result folder and predicted image. |
|
''' |
|
result2 = best_model_digits.predict([img2], save=True, iou=0.7, show_conf=False) |
|
|
|
|
|
result_path = result2[0].save_dir |
|
pred2_path = os.path.join(result_path, os.listdir(result_path)[0]) |
|
return result2, pred2_path |
|
|
|
def Sort_Digits(result2) : |
|
''' |
|
Sort detected labels base on their X-cordinate, |
|
--- Sort from lef to right --- |
|
''' |
|
list_of_items = [] |
|
for i in range(len(result2[0])) : |
|
|
|
class_label = classes_dict[str(int(result2[0][i].boxes.cls))] |
|
|
|
cord_x = int(result2[0][i].boxes.xyxy[0][0]) |
|
list_of_items.append((cord_x, class_label)) |
|
|
|
list_of_items.sort() |
|
list_of_items |
|
|
|
digits = [] |
|
for digit in list_of_items : |
|
digits.append(digit[1]) |
|
if len(digits) == 7 : digits.append('0') |
|
return digits |
|
|
|
|
|
raw_plate = ('raw_plate.png') |
|
|
|
def FINAL(img) : |
|
''' |
|
A pipeline for all parts of phase 3. |
|
start with a car image. |
|
result is digits and char on car plate. |
|
''' |
|
|
|
img = cv2.imread(img) |
|
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) |
|
|
|
|
|
result1, _ = Detect_Plate(img) |
|
|
|
|
|
pts = result1[0].boxes.xyxy.tolist()[0] |
|
|
|
|
|
img2 = img[round(pts[1]):round(pts[3]), round(pts[0]):round(pts[2])] |
|
|
|
|
|
img2 = cv2.resize(img2, (120, 70)) |
|
|
|
|
|
result2, _ = Detect_Digits(img2) |
|
|
|
|
|
digits = Sort_Digits(result2) |
|
|
|
Plot_Result(img, raw_plate, digits) |
|
|
|
if selected_type == "Upload Image": |
|
st.info('β¨ Supports all popular image formats π· - PNG, JPG, BMP π') |
|
uploaded_file = st.file_uploader("Upload Image of car's number plate π", type=["png","jpg","bmp","jpeg"]) |
|
|
|
if uploaded_file is not None: |
|
|
|
|
|
image = Image.open(uploaded_file).convert('RGB') |
|
st.image(image, use_column_width=True) |
|
|
|
|
|
img = cv2.imdecode(image, cv.IMREAD_COLOR) |
|
|
|
|
|
with st.spinner(f"Working... π«"): |
|
result = FINAL(img) |
|
|
|
st.image(result) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
else: |
|
st.warning('β Please upload your Image π―') |
|
|
|
st.markdown("<br><hr><center>Made with β€οΈ by <a href='https://omidsakaki.ir/'><strong>omid sakaki ghazvini</strong></a></center><hr>", unsafe_allow_html=True) |