|
|
import gradio as gr |
|
|
import torch |
|
|
import numpy as np |
|
|
import cv2 |
|
|
import sqlite3 |
|
|
import pandas as pd |
|
|
import matplotlib.pyplot as plt |
|
|
from PIL import Image, ImageDraw |
|
|
from transformers import YolosImageProcessor, YolosForObjectDetection |
|
|
import easyocr |
|
|
from datetime import datetime |
|
|
|
|
|
|
|
|
conn = sqlite3.connect("vehicles.db", check_same_thread=False) |
|
|
cursor = conn.cursor() |
|
|
cursor.execute(""" |
|
|
CREATE TABLE IF NOT EXISTS vehicles ( |
|
|
plate TEXT, |
|
|
type TEXT, |
|
|
time TEXT |
|
|
) |
|
|
""") |
|
|
conn.commit() |
|
|
|
|
|
|
|
|
processor = YolosImageProcessor.from_pretrained( |
|
|
"nickmuchi/yolos-small-finetuned-license-plate-detection" |
|
|
) |
|
|
model = YolosForObjectDetection.from_pretrained( |
|
|
"nickmuchi/yolos-small-finetuned-license-plate-detection" |
|
|
) |
|
|
model.eval() |
|
|
|
|
|
reader = easyocr.Reader(['en'], gpu=False) |
|
|
|
|
|
|
|
|
def classify_plate_color(plate_img): |
|
|
img = np.array(plate_img) |
|
|
hsv = cv2.cvtColor(img, cv2.COLOR_RGB2HSV) |
|
|
|
|
|
green = np.sum(cv2.inRange(hsv, (35, 40, 40), (85, 255, 255))) |
|
|
yellow = np.sum(cv2.inRange(hsv, (15, 50, 50), (35, 255, 255))) |
|
|
white = np.sum(cv2.inRange(hsv, (0, 0, 200), (180, 30, 255))) |
|
|
|
|
|
if green > yellow and green > white: |
|
|
return "EV" |
|
|
elif yellow > green and yellow > white: |
|
|
return "Commercial" |
|
|
else: |
|
|
return "Personal" |
|
|
|
|
|
|
|
|
def read_plate(plate_img): |
|
|
results = reader.readtext(np.array(plate_img)) |
|
|
if results: |
|
|
return results[0][1] |
|
|
return "UNKNOWN" |
|
|
|
|
|
|
|
|
def get_dashboard(): |
|
|
df = pd.read_sql("SELECT * FROM vehicles", conn) |
|
|
|
|
|
fig, ax = plt.subplots(figsize=(8, 5)) |
|
|
|
|
|
if len(df) == 0: |
|
|
ax.text(0.5, 0.5, "No vehicles scanned yet", |
|
|
ha="center", va="center", fontsize=10) |
|
|
ax.axis("off") |
|
|
return fig |
|
|
|
|
|
counts = df["type"].value_counts() |
|
|
counts.plot(kind="bar", ax=ax) |
|
|
|
|
|
ax.set_title("Vehicle Classification Dashboard") |
|
|
ax.set_xlabel("Vehicle Type") |
|
|
ax.set_ylabel("Count") |
|
|
ax.grid(axis="y") |
|
|
|
|
|
return fig |
|
|
|
|
|
|
|
|
def process_image(img): |
|
|
image = Image.fromarray(img) |
|
|
|
|
|
inputs = processor(images=image, return_tensors="pt") |
|
|
with torch.no_grad(): |
|
|
outputs = model(**inputs) |
|
|
|
|
|
results = processor.post_process_object_detection( |
|
|
outputs, |
|
|
threshold=0.3, |
|
|
target_sizes=torch.tensor([[image.size[1], image.size[0]]]) |
|
|
)[0] |
|
|
|
|
|
draw = ImageDraw.Draw(image) |
|
|
|
|
|
if len(results["boxes"]) == 0: |
|
|
return image, "No plate detected", "", get_dashboard() |
|
|
|
|
|
x1, y1, x2, y2 = map(int, results["boxes"][0].tolist()) |
|
|
plate_img = image.crop((x1, y1, x2, y2)) |
|
|
|
|
|
plate_text = read_plate(plate_img) |
|
|
vehicle_type = classify_plate_color(plate_img) |
|
|
|
|
|
cursor.execute( |
|
|
"INSERT INTO vehicles VALUES (?, ?, ?)", |
|
|
(plate_text, vehicle_type, datetime.now().strftime("%Y-%m-%d %H:%M:%S")) |
|
|
) |
|
|
conn.commit() |
|
|
|
|
|
draw.rectangle([x1, y1, x2, y2], outline="red", width=3) |
|
|
draw.text((x1, y1 - 12), f"{plate_text} | {vehicle_type}", fill="red") |
|
|
|
|
|
return image, plate_text, vehicle_type, get_dashboard() |
|
|
|
|
|
|
|
|
css = """ |
|
|
textarea { |
|
|
white-space: pre-wrap !important; |
|
|
word-break: break-word !important; |
|
|
overflow-wrap: break-word !important; |
|
|
} |
|
|
""" |
|
|
|
|
|
with gr.Blocks() as demo: |
|
|
gr.Markdown("## Smart Traffic & EV Analytics System") |
|
|
gr.Markdown( |
|
|
"Detects license plates, reads number plate text, " |
|
|
"classifies EV / Commercial / Personal vehicles, " |
|
|
"and shows live analytics." |
|
|
) |
|
|
|
|
|
with gr.Row(): |
|
|
input_img = gr.Image(type="numpy", sources=["upload", "webcam"]) |
|
|
output_img = gr.Image() |
|
|
|
|
|
with gr.Row(): |
|
|
plate_box = gr.Textbox(label="Number Plate") |
|
|
type_box = gr.Textbox(label="Vehicle Type") |
|
|
|
|
|
dashboard = gr.Plot(label="Live Vehicle Dashboard") |
|
|
|
|
|
btn = gr.Button("Scan Vehicle") |
|
|
btn.click( |
|
|
process_image, |
|
|
input_img, |
|
|
[output_img, plate_box, type_box, dashboard] |
|
|
) |
|
|
|
|
|
demo.launch(css=css) |
|
|
|