Sarvamangalak commited on
Commit
cddf5d6
·
verified ·
1 Parent(s): d9bea70

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +100 -255
app.py CHANGED
@@ -1,275 +1,120 @@
1
- import io
2
  import cv2
3
- import gradio as gr
4
- import matplotlib
5
- matplotlib.use("Agg")
6
-
7
- import matplotlib.pyplot as plt
8
- import torch
9
  import numpy as np
10
- import sqlite3
11
- import pandas as pd
12
  import pytesseract
13
-
14
- from PIL import Image
15
- from transformers import YolosImageProcessor, YolosForObjectDetection
16
-
17
- # ---------------- CONFIG ----------------
18
-
19
- MODEL_NAME = "nickmuchi/yolos-small-finetuned-license-plate-detection"
20
- BASE_AMT = 100
21
-
22
- # ---------------- DATABASE ----------------
23
-
24
- conn = sqlite3.connect("vehicles.db", check_same_thread=False)
25
- cursor = conn.cursor()
26
-
27
- cursor.execute("""
28
- CREATE TABLE IF NOT EXISTS vehicles (
29
- plate TEXT,
30
- type TEXT,
31
- amount REAL,
32
- time TEXT
33
- )
34
- """)
35
-
36
- cursor.execute("""
37
- CREATE TABLE IF NOT EXISTS feedback (
38
- result TEXT,
39
- feedback TEXT
40
- )
41
- """)
42
-
43
- conn.commit()
44
-
45
- # ---------------- MODEL (Lazy Load) ----------------
46
-
47
- processor = None
48
- model = None
49
-
50
- def load_model():
51
- global processor, model
52
- if processor is None:
53
- processor = YolosImageProcessor.from_pretrained(MODEL_NAME)
54
- model = YolosForObjectDetection.from_pretrained(MODEL_NAME)
55
- model.eval()
56
- return processor, model
57
-
58
- # ---------------- LOGIC ----------------
59
-
60
- def compute_discount(vehicle_type):
61
- if vehicle_type == "EV":
62
- return BASE_AMT * 0.9
63
- return BASE_AMT
64
-
65
- def classify_plate_color(plate_img):
66
  hsv = cv2.cvtColor(plate_img, cv2.COLOR_BGR2HSV)
 
67
 
68
- # Masks for colors
69
- masks = {}
70
-
71
- # White
72
- masks["white"] = cv2.inRange(hsv, np.array([0, 0, 180]), np.array([180, 60, 255]))
73
-
74
- # Yellow
75
- masks["yellow"] = cv2.inRange(hsv, np.array([15, 80, 80]), np.array([40, 255, 255]))
76
-
77
- # Green
78
- masks["green"] = cv2.inRange(hsv, np.array([35, 50, 50]), np.array([85, 255, 255]))
79
-
80
- # Red
81
- masks["red1"] = cv2.inRange(hsv, np.array([0, 70, 50]), np.array([10, 255, 255]))
82
- masks["red2"] = cv2.inRange(hsv, np.array([170, 70, 50]), np.array([180, 255, 255]))
83
- masks["red"] = masks["red1"] + masks["red2"]
84
-
85
- # Blue
86
- masks["blue"] = cv2.inRange(hsv, np.array([90, 50, 50]), np.array([130, 255, 255]))
87
-
88
- # Count pixels
89
- color_counts = {color: np.sum(mask) for color, mask in masks.items()}
90
-
91
- dominant_color = max(color_counts, key=color_counts.get)
92
-
93
- # Classification logic
94
- if dominant_color == "white":
95
- return "Private Vehicle"
96
- elif dominant_color == "yellow":
97
- return "Commercial Vehicle"
98
- elif dominant_color == "green":
99
- return "Electric Vehicle (EV)"
100
- elif dominant_color == "red":
101
- return "Temporary Registration Vehicle"
102
- elif dominant_color == "blue":
103
- return "Diplomatic Vehicle"
104
  else:
105
- return "Unknown Vehicle Type"
106
-
107
- def read_plate(plate_img):
108
- try:
109
- gray = cv2.cvtColor(np.array(plate_img), cv2.COLOR_RGB2GRAY)
110
- gray = cv2.threshold(gray, 120, 255, cv2.THRESH_BINARY)[1]
111
-
112
- text = pytesseract.image_to_string(
113
- gray,
114
- config="--psm 7 -c tessedit_char_whitelist=ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
115
- )
116
- return text.strip() if text.strip() else "UNKNOWN"
117
- except:
118
- return "UNKNOWN"
119
-
120
- def make_prediction(img):
121
- processor, model = load_model()
122
- inputs = processor(images=img, return_tensors="pt")
123
-
124
- with torch.no_grad():
125
- outputs = model(**inputs)
126
-
127
- img_size = torch.tensor([img.size[::-1]])
128
- results = processor.post_process_object_detection(
129
- outputs, threshold=0.3, target_sizes=img_size
130
- )
131
-
132
- return results[0], model.config.id2label
133
-
134
- # ---------------- VISUALIZATION ----------------
135
-
136
- def visualize(img, output, id2label, threshold):
137
- try:
138
- keep = output["scores"] > threshold
139
- boxes = output["boxes"][keep]
140
- labels = output["labels"][keep]
141
-
142
- fig, ax = plt.subplots(figsize=(6,6))
143
- ax.imshow(img)
144
- results_text = []
145
-
146
- for box, label in zip(boxes, labels):
147
- label_name = id2label[label.item()].lower()
148
-
149
- if "plate" not in label_name:
150
- continue
151
-
152
- x1,y1,x2,y2 = map(int, box.tolist())
153
- plate_img = img.crop((x1,y1,x2,y2))
154
-
155
- plate = read_plate(plate_img)
156
- vtype = classify_plate_color(plate_img)
157
- toll = compute_discount(vtype)
158
-
159
- cursor.execute(
160
- "INSERT INTO vehicles VALUES (?, ?, ?, datetime('now'))",
161
- (plate, vtype, toll)
162
- )
163
- conn.commit()
164
-
165
- results_text.append(f"{plate} | {vtype} | ₹{int(toll)}")
166
-
167
- ax.add_patch(
168
- plt.Rectangle((x1,y1), x2-x1, y2-y1,
169
- fill=False, color="red", linewidth=2)
170
- )
171
- ax.text(x1, y1-5, f"{plate} ({vtype})",
172
- color="yellow", fontsize=8)
173
-
174
- ax.axis("off")
175
-
176
- if not results_text:
177
- return fig, "No plate detected"
178
-
179
- return fig, "\n".join(results_text)
180
-
181
- except Exception as e:
182
- return None, f"Error: {str(e)}"
183
-
184
- # ---------------- DASHBOARD ----------------
185
-
186
- def get_dashboard():
187
- df = pd.read_sql("SELECT * FROM vehicles", conn)
188
- fig, ax = plt.subplots()
189
-
190
- if df.empty:
191
- ax.text(0.5,0.5,"No data yet",ha="center")
192
- ax.axis("off")
193
- return fig
194
-
195
- df["type"].value_counts().plot(kind="bar", ax=ax)
196
- ax.set_title("Vehicle Types")
197
- return fig
198
-
199
- # ---------------- FEEDBACK ----------------
200
-
201
- def submit_feedback(result_text, feedback_choice):
202
- if not result_text:
203
- return "No result available."
204
-
205
- cursor.execute(
206
- "INSERT INTO feedback VALUES (?, ?)",
207
- (result_text, feedback_choice)
208
- )
209
- conn.commit()
210
- return "Feedback recorded!"
211
-
212
- def show_accuracy():
213
- df = pd.read_sql("SELECT * FROM feedback", conn)
214
-
215
- if df.empty:
216
- return "No feedback yet."
217
-
218
- correct = len(df[df["feedback"] == "Correct"])
219
- total = len(df)
220
-
221
- accuracy = (correct / total) * 100
222
- return f"Accuracy (User Feedback Based): {accuracy:.2f}%"
223
-
224
- # ---------------- CALLBACK ----------------
225
 
226
- def detect_image(img, threshold):
227
- if img is None:
228
- return None, "No image provided"
229
- output, id2label = make_prediction(img)
230
- return visualize(img, output, id2label, threshold)
231
 
232
- # ---------------- UI ----------------
233
 
234
- with gr.Blocks() as demo:
235
- gr.Markdown("## Smart Vehicle Classification System")
 
 
236
 
237
- slider = gr.Slider(0.3, 1.0, 0.5, label="Confidence Threshold")
 
 
 
238
 
239
- with gr.Row():
240
- img_input = gr.Image(type="pil")
241
- img_output = gr.Plot()
 
 
242
 
243
- result_box = gr.Textbox(label="Detection Result", lines=4)
 
 
 
244
 
245
- detect_btn = gr.Button("Detect")
246
- detect_btn.click(
247
- detect_image,
248
- inputs=[img_input, slider],
249
- outputs=[img_output, result_box]
250
- )
251
 
252
- gr.Markdown("### Feedback")
253
- feedback_radio = gr.Radio(["Correct", "Incorrect"], label="Prediction correct?")
254
- feedback_btn = gr.Button("Submit Feedback")
255
- feedback_msg = gr.Textbox(label="Feedback Status")
256
 
257
- feedback_btn.click(
258
- submit_feedback,
259
- inputs=[result_box, feedback_radio],
260
- outputs=feedback_msg
261
- )
262
 
263
- gr.Markdown("### Model Accuracy")
264
- accuracy_btn = gr.Button("Show Accuracy")
265
- accuracy_box = gr.Textbox(label="Accuracy")
266
 
267
- accuracy_btn.click(show_accuracy, outputs=accuracy_box)
 
 
 
 
 
268
 
269
- gr.Markdown("### Dashboard")
270
- dashboard_plot = gr.Plot()
 
 
 
 
 
271
 
272
- refresh_btn = gr.Button("Refresh Dashboard")
273
- refresh_btn.click(get_dashboard, outputs=dashboard_plot)
274
 
275
- demo.launch()
 
 
1
  import cv2
 
 
 
 
 
 
2
  import numpy as np
 
 
3
  import pytesseract
4
+ from ultralytics import YOLO
5
+ from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score
6
+
7
+ # ---------------------------------------------------
8
+ # 1️⃣ Load YOLO Model
9
+ # ---------------------------------------------------
10
+ model = YOLO("best.pt") # Your trained number plate model
11
+
12
+ # ---------------------------------------------------
13
+ # 2️⃣ Detect Number Plate
14
+ # ---------------------------------------------------
15
+ def detect_plate(image):
16
+ results = model(image)[0]
17
+ boxes = results.boxes
18
+
19
+ plates = []
20
+
21
+ for box in boxes:
22
+ x1, y1, x2, y2 = map(int, box.xyxy[0])
23
+ cropped = image[y1:y2, x1:x2]
24
+ plates.append((cropped, (x1, y1, x2, y2)))
25
+
26
+ return plates
27
+
28
+ # ---------------------------------------------------
29
+ # 3️⃣ OCR Extraction
30
+ # ---------------------------------------------------
31
+ def extract_text(plate_img):
32
+ gray = cv2.cvtColor(plate_img, cv2.COLOR_BGR2GRAY)
33
+ text = pytesseract.image_to_string(gray, config='--psm 8')
34
+ text = "".join(filter(str.isalnum, text))
35
+ return text
36
+
37
+ # ---------------------------------------------------
38
+ # 4️⃣ Detect Plate Colour
39
+ # ---------------------------------------------------
40
+ def detect_plate_color(plate_img):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
41
  hsv = cv2.cvtColor(plate_img, cv2.COLOR_BGR2HSV)
42
+ avg_color = np.mean(hsv[:, :, 0])
43
 
44
+ if 35 < avg_color < 85:
45
+ return "Green"
46
+ elif 15 < avg_color < 35:
47
+ return "Yellow"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
48
  else:
49
+ return "White"
50
+
51
+ # ---------------------------------------------------
52
+ # 5️⃣ EV Discount Logic
53
+ # ---------------------------------------------------
54
+ def calculate_ev_discount(plate_color, base_toll=100):
55
+
56
+ if plate_color == "Green":
57
+ discount = 0.50 * base_toll
58
+ vehicle_type = "Electric Vehicle (EV)"
59
+ elif plate_color == "Yellow":
60
+ discount = 0.10 * base_toll
61
+ vehicle_type = "Commercial Vehicle"
62
+ else:
63
+ discount = 0
64
+ vehicle_type = "Private Non-EV"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
65
 
66
+ final_toll = base_toll - discount
 
 
 
 
67
 
68
+ return vehicle_type, discount, final_toll
69
 
70
+ # ---------------------------------------------------
71
+ # 6️⃣ Evaluation Metrics
72
+ # ---------------------------------------------------
73
+ def evaluate_metrics(y_true, y_pred):
74
 
75
+ accuracy = accuracy_score(y_true, y_pred)
76
+ precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
77
+ recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
78
+ f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
79
 
80
+ print("\n===== Classification Metrics =====")
81
+ print(f"Accuracy : {accuracy:.4f}")
82
+ print(f"Precision : {precision:.4f}")
83
+ print(f"Recall : {recall:.4f}")
84
+ print(f"F1 Score : {f1:.4f}")
85
 
86
+ # ---------------------------------------------------
87
+ # 7️⃣ Main Processing Function
88
+ # ---------------------------------------------------
89
+ def process_image(image_path):
90
 
91
+ image = cv2.imread(image_path)
92
+ plates = detect_plate(image)
 
 
 
 
93
 
94
+ results_summary = []
 
 
 
95
 
96
+ for plate_img, bbox in plates:
 
 
 
 
97
 
98
+ text = extract_text(plate_img)
99
+ color = detect_plate_color(plate_img)
100
+ vehicle_type, discount, final_toll = calculate_ev_discount(color)
101
 
102
+ results_summary.append({
103
+ "Plate": text,
104
+ "Type": vehicle_type,
105
+ "Discount": discount,
106
+ "Final Toll": final_toll
107
+ })
108
 
109
+ # Draw bounding box
110
+ x1, y1, x2, y2 = bbox
111
+ cv2.rectangle(image, (x1, y1), (x2, y2), (0, 255, 0), 2)
112
+ cv2.putText(image, f"{text} | {vehicle_type}",
113
+ (x1, y1 - 10),
114
+ cv2.FONT_HERSHEY_SIMPLEX,
115
+ 0.7, (0, 255, 0), 2)
116
 
117
+ cv2.imshow("Output", image)
118
+ cv2.waitKey(0)
119
 
120
+ return results_summary