Sarvamangalak's picture
Update app.py
a6a8190 verified
Raw
History Blame Contribute Delete
8.92 kB
# Author Sarvamangala Kokatanur
# Import libraries
import gradio as gr
import torch
import numpy as np
import cv2
import sqlite3
import pandas as pd
import matplotlib.pyplot as plt
from datetime import datetime, timedelta
from PIL import Image, ImageDraw
from transformers import (
YolosImageProcessor,
YolosForObjectDetection
)
# Load model
processor = YolosImageProcessor.from_pretrained(
"nickmuchi/yolos-small-finetuned-license-plate-detection"
)
model = YolosForObjectDetection.from_pretrained(
"nickmuchi/yolos-small-finetuned-license-plate-detection"
)
model.eval()
# ---------------- DATABASE ----------------
conn = sqlite3.connect(
"vehicles.db",
check_same_thread=False
)
cursor = conn.cursor()
cursor.execute("""
CREATE TABLE IF NOT EXISTS vehicles(
id INTEGER PRIMARY KEY AUTOINCREMENT,
timestamp TEXT,
license_plate TEXT,
vehicle_status TEXT,
discount INTEGER
)
""")
conn.commit()
# -------- Plate Color Classifier -------- #
def classify_plate_color(plate_img):
img = np.array(plate_img)
# Convert RGB → HSV
hsv = cv2.cvtColor(img, cv2.COLOR_RGB2HSV)
h, w = hsv.shape[:2]
# Only inspect the left 20% of the plate
left = hsv[:, :int(w*0.2)]
# Green mask
green = cv2.inRange(
left,
(35, 40, 40),
(90, 255, 255)
)
green_ratio = np.count_nonzero(green) / green.size
# If more than 15% of the left strip is green,
# classify as EV
if green_ratio > 0.15:
return "EV"
return "Non-EV"
# Avoid duplicate vehicle details to the dashboard
def is_duplicate_vehicle(plate_number):
cursor.execute("""
SELECT timestamp
FROM vehicles
WHERE license_plate=?
ORDER BY id DESC
LIMIT 1
""",(plate_number,))
row = cursor.fetchone()
if row is None:
return False
last_time = datetime.strptime(
row[0],
"%Y-%m-%d %H:%M:%S"
)
if datetime.now() - last_time < timedelta(minutes=5):
return True
return False
# to save vehicle details in the database
def save_vehicle(plate,status):
if status=="EV":
discount=50
else:
discount=0
if is_duplicate_vehicle(plate):
return "Duplicate"
current_time=datetime.now().strftime(
"%Y-%m-%d %H:%M:%S"
)
cursor.execute("""
INSERT INTO vehicles(
timestamp,
license_plate,
vehicle_status,
discount
)
VALUES(?,?,?,?)
""",
(
current_time,
plate,
status,
discount
))
conn.commit()
return "Saved"
# --------get_dashboard function ------#
def get_dashboard():
df = pd.read_sql(
"SELECT * FROM vehicles",
conn
)
fig, axs = plt.subplots(2, 2, figsize=(8, 6))
if df.empty:
for ax in axs.flatten():
ax.text(
0.5,
0.5,
"No Data Available",
ha="center",
va="center",
fontsize=10
)
ax.axis("off")
plt.tight_layout()
return fig
status_counts = df["vehicle_status"].value_counts()
axs[0,0].bar(
status_counts.index,
status_counts.values
)
axs[0,0].set_title("EV vs Non-EV")
if status_counts.empty:
plt.tight_layout()
return fig
axs[0,1].pie(
status_counts.values,
labels=status_counts.index,
autopct="%1.1f%%"
)
axs[0,1].set_title("Vehicle Distribution")
total_discount = df["discount"].sum()
axs[1,0].bar(
["Discount"],
[total_discount]
)
axs[1,0].set_title("Total Discount")
axs[1,1].axis("off")
report = (
f"Today's Report\n\n"
f"Total Vehicles : {len(df)}\n\n"
f"EV : {len(df[df.vehicle_status=='EV'])}\n\n"
f"Non-EV : {len(df[df.vehicle_status=='Non-EV'])}\n\n"
f"Discount Given : ₹{total_discount}"
)
axs[1,1].text(
0,
1,
report,
fontsize=10,
va="top"
)
plt.tight_layout()
plt.close(fig)
return fig
# -------- Main Pipeline -------- #
def process_image(img):
if img is None:
return (
None,
"Please upload an image.",
"0",
"0",
"₹0",
get_dashboard()
)
image = Image.fromarray(img)
inputs = processor(images=image, return_tensors="pt")
with torch.no_grad():
outputs = model(**inputs)
target_sizes = torch.tensor([[image.size[1], image.size[0]]])
results = processor.post_process_object_detection(
outputs,
threshold=0.3,
target_sizes=target_sizes
)[0]
draw = ImageDraw.Draw(image)
ev_count = 0
non_ev_count = 0
discount_total = 0
output_text = ""
# No detection
if len(results["boxes"]) == 0:
return (
image,
"No license plate detected.",
"0",
"0",
"₹0",
get_dashboard()
)
# Process each detected plate
for i, box in enumerate(results["boxes"]):
x1, y1, x2, y2 = map(int, box.tolist())
plate = image.crop((x1, y1, x2, y2))
status = classify_plate_color(plate)
# Temporary plate number
# Replace with OCR later
plate_number = f"Vehicle_{datetime.now().strftime('%H%M%S%f')}_{i}"
saved = save_vehicle(
plate_number,
status
)
# Skip duplicate entries
if saved == "Duplicate":
continue
if status == "EV":
ev_count += 1
discount = 50
discount_total += discount
color = "green"
label = f"{plate_number}\nEV | ₹{discount}"
else:
non_ev_count += 1
discount = 0
color = "red"
label = f"{plate_number}\nNon-EV"
# Draw bounding box
draw.rectangle(
[x1, y1, x2, y2],
outline=color,
width=3
)
# Draw label
draw.text(
(x1, max(0, y1 - 30)),
label,
fill=color
)
output_text += (
f"Vehicle {i+1}\n"
f"Plate : {plate_number}\n"
f"Status : {status}\n"
f"Discount : ₹{discount}\n\n"
)
conn.commit()
dashboard = get_dashboard()
return (
image,
output_text,
str(ev_count),
str(non_ev_count),
f"₹{discount_total}",
dashboard
)
# -------- Gradio UI -------- #
css = """
.gradio-container{
max-width:98% !important;
margin:auto;
}
textarea{
font-size:15px !important;
}
h1{
text-align:center;
}
.block{
border-radius:12px;
}
.gr-image{
min-height:350px;
}
"""
with gr.Blocks() as demo:
gr.Markdown("# Smart Traffic & EV Analytics System")
gr.Markdown(
"Automatic License Plate Detection • EV Classification • Discount Calculation"
)
##################################################
# TOP SECTION
##################################################
with gr.Row(equal_height=True):
# LEFT
with gr.Column(scale=1):
input_img = gr.Image(
type="numpy",
label="Input Image",
sources=["upload","webcam"],
height=350
)
btn = gr.Button(
"Scan Vehicle",
variant="primary",
size="lg"
)
# CENTER
with gr.Column(scale=1):
output_img = gr.Image(
label="Detection Result",
height=350
)
# RIGHT
with gr.Column(scale=1):
summary_box = gr.Textbox(
label="Detection Summary",
lines=16
)
##################################################
# STATISTICS
##################################################
with gr.Row():
ev_box = gr.Textbox(
label="EV Vehicles"
)
non_ev_box = gr.Textbox(
label="Non-EV Vehicles"
)
discount_box = gr.Textbox(
label="Total Discount"
)
##################################################
# DASHBOARD
##################################################
gr.Markdown("## 📊 Today's Traffic Dashboard")
dashboard = gr.Plot(label="Analytics")
btn.click(
fn=process_image,
inputs=input_img,
outputs=[
output_img,
summary_box,
ev_box,
non_ev_box,
discount_box,
dashboard
]
)
if __name__ == "__main__":
demo.queue()
demo.launch(
ssr_mode=False
)