Sarvamangalak commited on
Commit
c11d90d
·
verified ·
1 Parent(s): 5e01346

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +200 -202
app.py CHANGED
@@ -1,251 +1,249 @@
 
 
1
  import gradio as gr
 
 
 
2
  import matplotlib.pyplot as plt
 
 
 
3
  import pandas as pd
4
- import os
5
- import random
6
- from PIL import ImageDraw
7
-
8
- # ===============================
9
- # GLOBAL VARIABLES
10
- # ===============================
11
- total_vehicles = 0
12
- ev_count = 0
13
- total_co2_saved = 0
14
-
15
- DISTANCE_KM = 10
16
- CO2_PER_KM_PETROL = 0.150
17
- CO2_SAVED_PER_EV = DISTANCE_KM * CO2_PER_KM_PETROL
18
-
19
- FEEDBACK_FILE = "feedback.csv"
20
-
21
- if not os.path.exists(FEEDBACK_FILE):
22
- pd.DataFrame(columns=["Predicted_Label", "Feedback"]).to_csv(FEEDBACK_FILE, index=False)
23
-
24
- # ===============================
25
- # SIMULATED NUMBER PLATE COLOUR DETECTION
26
- # Replace with real color detection later
27
- # ===============================
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
28
  def classify_plate_color(plate_img):
29
  try:
30
  img = np.array(plate_img)
31
- img = cv2.GaussianBlur(img, (5,5), 0)
32
  hsv = cv2.cvtColor(img, cv2.COLOR_RGB2HSV)
33
 
34
- green_mask = cv2.inRange(hsv, (35, 40, 40), (85, 255, 255))
35
- yellow_mask = cv2.inRange(hsv, (15, 50, 50), (35, 255, 255))
36
- white_mask = cv2.inRange(hsv, (0, 0, 200), (180, 40, 255))
37
-
38
- green = np.sum(green_mask)
39
- yellow = np.sum(yellow_mask)
40
- white = np.sum(white_mask)
41
-
42
- if green > yellow and green > white:
43
- return "Electric Vehicle (Green Plate)"
44
- elif yellow > green and yellow > white:
45
- return "Commercial Vehicle (Yellow Plate)"
46
- elif white > green and white > yellow:
47
- return "Private Vehicle (White Plate)"
48
- else:
49
- return "Unknown Classification"
50
 
 
 
 
 
 
51
  except:
52
- return "Unknown Classification"
53
 
 
 
 
 
 
 
 
 
 
 
 
 
54
 
 
 
 
55
 
56
- def get_vehicle_type_from_colour(colour):
57
- mapping = {
58
- "White": "Private Vehicle",
59
- "Yellow": "Commercial Vehicle",
60
- "Green": "Electric Vehicle",
61
- "Black": "Rental Vehicle"
62
- }
63
- return mapping.get(colour, "Unknown")
64
 
65
- # ===============================
66
- # DASHBOARD
67
- # ===============================
68
- def generate_dashboard():
69
- global total_vehicles, ev_count
70
- non_ev = total_vehicles - ev_count
71
 
72
- fig, ax = plt.subplots()
73
- ax.bar(["EV", "Non-EV"], [ev_count, non_ev])
74
- ax.set_title("Vehicle Distribution")
75
- ax.set_ylabel("Count")
76
- return fig
77
 
78
- # ===============================
79
- # EVALUATION SUMMARY
80
- # ===============================
81
- def get_evaluation_summary():
82
- df = pd.read_csv(FEEDBACK_FILE)
83
- total = len(df)
84
- correct = len(df[df["Feedback"] == "Correct"])
85
- incorrect = len(df[df["Feedback"] == "Incorrect"])
86
 
87
- if total == 0:
88
- return "Evaluation Summary:\nNo feedback yet."
 
 
 
89
 
90
- precision = correct / total
 
 
91
 
92
- return f"""Evaluation Summary
93
- Total: {total}
94
- Correct: {correct}
95
- Incorrect: {incorrect}
96
- Accuracy: {precision:.2f}
97
- """
98
 
99
- # ===============================
100
- # DETECTION FUNCTION
101
- # ===============================
102
- def detect_image(image):
103
 
104
- global total_vehicles, ev_count, total_co2_saved
 
105
 
106
- if image is None:
107
- return None, "Upload image first.", "", "", "", "", "", ""
 
108
 
109
- plate_colour = detect_plate_colour()
110
- vehicle_type = classify_plate_color(plate_colour)
111
- plate_number = "KA01AB1234"
 
 
112
 
113
- total_vehicles += 1
114
- co2_saved_this = 0
115
 
116
- if vehicle_type == "Electric Vehicle":
117
- ev_count += 1
118
- co2_saved_this = CO2_SAVED_PER_EV
119
- total_co2_saved += co2_saved_this
 
 
120
 
121
- ev_percent = (ev_count / total_vehicles) * 100
122
 
123
- # Draw boxes
124
- img = image.copy()
125
- draw = ImageDraw.Draw(img)
126
- w, h = img.size
127
 
128
- vehicle_box = [w*0.1, h*0.2, w*0.9, h*0.8]
129
- plate_box = [w*0.4, h*0.6, w*0.7, h*0.75]
130
 
131
- draw.rectangle(vehicle_box, outline="red", width=4)
132
- draw.text((vehicle_box[0], vehicle_box[1]-20),
133
- f"{vehicle_type}", fill="red")
134
 
135
- draw.rectangle(plate_box, outline="green", width=4)
136
- draw.text((plate_box[0], plate_box[1]-20),
137
- f"{plate_number} ({plate_colour})", fill="green")
138
 
 
 
139
  fig, ax = plt.subplots()
140
- ax.imshow(img)
141
- ax.axis("off")
142
-
143
- result_text = f"""
144
- Vehicle Type: {vehicle_type}
145
- Plate Colour: {plate_colour}
146
- Plate Number: {plate_number}
147
- CO₂ Saved: {co2_saved_this:.2f} kg
148
- """
149
-
150
- total_card = f"### 🚘 Total: {total_vehicles}"
151
- ev_card = f"### ⚡ EV: {ev_count}"
152
- percent_card = f"### 📊 EV Rate: {ev_percent:.2f}%"
153
- co2_card = f"### 🌱 CO₂ Saved: {total_co2_saved:.2f} kg"
154
-
155
- dashboard_fig = generate_dashboard()
156
-
157
- summary = get_evaluation_summary()
158
-
159
- return fig, result_text, total_card, ev_card, percent_card, co2_card, dashboard_fig, vehicle_type, summary
160
-
161
- # ===============================
162
- # FEEDBACK SAVE
163
- # ===============================
164
- def save_feedback(predicted_label, feedback):
165
- df = pd.read_csv(FEEDBACK_FILE)
166
- df = pd.concat([df, pd.DataFrame(
167
- [{"Predicted_Label": predicted_label, "Feedback": feedback}]
168
- )], ignore_index=True)
169
- df.to_csv(FEEDBACK_FILE, index=False)
170
- return "Saved!", get_evaluation_summary()
171
-
172
- # ===============================
173
- # RESET DATABASE
174
- # ===============================
175
- def reset_database():
176
- pd.DataFrame(columns=["Predicted_Label", "Feedback"]).to_csv(FEEDBACK_FILE, index=False)
177
- return "Database Reset!", "Evaluation Summary:\nNo feedback yet."
178
-
179
- # ===============================
180
- # UI
181
- # ===============================
182
- with gr.Blocks() as demo:
183
 
184
- gr.Markdown("## 🚦 Smart Vehicle Detection Based on Number Plate Colour")
 
 
 
185
 
186
- with gr.Row():
187
- img_input = gr.Image(type="pil", label="Upload Vehicle Image")
188
- img_output = gr.Plot()
189
 
190
- detect_btn = gr.Button("Detect", size="sm")
191
 
192
- result_box = gr.Textbox(label="Detection Result", lines=5)
 
 
193
 
194
- with gr.Row():
195
- total_card = gr.Markdown("### 🚘 Total: 0")
196
- ev_card = gr.Markdown("### ⚡ EV: 0")
197
- percent_card = gr.Markdown("### 📊 EV Rate: 0%")
198
- co2_card = gr.Markdown("### 🌱 CO₂ Saved: 0 kg")
 
199
 
200
- dashboard_plot = gr.Plot()
 
201
 
202
- predicted_label_state = gr.State()
 
203
 
204
- detect_btn.click(
205
- fn=detect_image,
206
- inputs=[img_input],
207
- outputs=[
208
- img_output,
209
- result_box,
210
- total_card,
211
- ev_card,
212
- percent_card,
213
- co2_card,
214
- dashboard_plot,
215
- predicted_label_state,
216
- gr.Markdown() # evaluation summary placeholder
217
- ]
218
- )
219
 
220
- # -------------------------
221
- # FEEDBACK + EVALUATION ROW
222
- # -------------------------
223
- with gr.Row():
224
 
225
- with gr.Column(scale=1):
226
- correct_btn = gr.Button("✔", size="sm")
227
- incorrect_btn = gr.Button("✘", size="sm")
228
- feedback_status = gr.Textbox(label="Feedback", lines=1)
229
 
230
- with gr.Column(scale=1):
231
- evaluation_summary = gr.Textbox(label="Evaluation Summary", lines=6)
 
 
 
232
 
233
- correct_btn.click(
234
- fn=save_feedback,
235
- inputs=[predicted_label_state, gr.State("Correct")],
236
- outputs=[feedback_status, evaluation_summary]
237
- )
238
 
239
- incorrect_btn.click(
240
- fn=save_feedback,
241
- inputs=[predicted_label_state, gr.State("Incorrect")],
242
- outputs=[feedback_status, evaluation_summary]
 
 
 
 
 
 
 
 
 
243
  )
244
 
245
- reset_btn = gr.Button("Reset Database", size="sm")
246
- reset_btn.click(
247
- fn=reset_database,
248
- outputs=[feedback_status, evaluation_summary]
 
 
 
 
 
249
  )
250
 
251
- demo.launch(theme=gr.themes.Soft())
 
 
 
 
 
 
 
 
 
 
 
 
 
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
  try:
67
  img = np.array(plate_img)
 
68
  hsv = cv2.cvtColor(img, cv2.COLOR_RGB2HSV)
69
 
70
+ green = np.sum(cv2.inRange(hsv, (35,40,40), (85,255,255)))
71
+ yellow = np.sum(cv2.inRange(hsv, (15,50,50), (35,255,255)))
 
 
 
 
 
 
 
 
 
 
 
 
 
 
72
 
73
+ if green > yellow:
74
+ return "EV"
75
+ elif yellow > green:
76
+ return "Commercial"
77
+ return "Personal"
78
  except:
79
+ return "Unknown"
80
 
81
+ def read_plate(plate_img):
82
+ try:
83
+ gray = cv2.cvtColor(np.array(plate_img), cv2.COLOR_RGB2GRAY)
84
+ gray = cv2.threshold(gray, 120, 255, cv2.THRESH_BINARY)[1]
85
+
86
+ text = pytesseract.image_to_string(
87
+ gray,
88
+ config="--psm 7 -c tessedit_char_whitelist=ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
89
+ )
90
+ return text.strip() if text.strip() else "UNKNOWN"
91
+ except:
92
+ return "UNKNOWN"
93
 
94
+ def make_prediction(img):
95
+ processor, model = load_model()
96
+ inputs = processor(images=img, return_tensors="pt")
97
 
98
+ with torch.no_grad():
99
+ outputs = model(**inputs)
 
 
 
 
 
 
100
 
101
+ img_size = torch.tensor([img.size[::-1]])
102
+ results = processor.post_process_object_detection(
103
+ outputs, threshold=0.3, target_sizes=img_size
104
+ )
 
 
105
 
106
+ return results[0], model.config.id2label
 
 
 
 
107
 
108
+ # ---------------- VISUALIZATION ----------------
 
 
 
 
 
 
 
109
 
110
+ def visualize(img, output, id2label, threshold):
111
+ try:
112
+ keep = output["scores"] > threshold
113
+ boxes = output["boxes"][keep]
114
+ labels = output["labels"][keep]
115
 
116
+ fig, ax = plt.subplots(figsize=(6,6))
117
+ ax.imshow(img)
118
+ results_text = []
119
 
120
+ for box, label in zip(boxes, labels):
121
+ label_name = id2label[label.item()].lower()
 
 
 
 
122
 
123
+ if "plate" not in label_name:
124
+ continue
 
 
125
 
126
+ x1,y1,x2,y2 = map(int, box.tolist())
127
+ plate_img = img.crop((x1,y1,x2,y2))
128
 
129
+ plate = read_plate(plate_img)
130
+ vtype = classify_plate_color(plate_img)
131
+ toll = compute_discount(vtype)
132
 
133
+ cursor.execute(
134
+ "INSERT INTO vehicles VALUES (?, ?, ?, datetime('now'))",
135
+ (plate, vtype, toll)
136
+ )
137
+ conn.commit()
138
 
139
+ results_text.append(f"{plate} | {vtype} | ₹{int(toll)}")
 
140
 
141
+ ax.add_patch(
142
+ plt.Rectangle((x1,y1), x2-x1, y2-y1,
143
+ fill=False, color="red", linewidth=2)
144
+ )
145
+ ax.text(x1, y1-5, f"{plate} ({vtype})",
146
+ color="yellow", fontsize=8)
147
 
148
+ ax.axis("off")
149
 
150
+ if not results_text:
151
+ return fig, "No plate detected"
 
 
152
 
153
+ return fig, "\n".join(results_text)
 
154
 
155
+ except Exception as e:
156
+ return None, f"Error: {str(e)}"
 
157
 
158
+ # ---------------- DASHBOARD ----------------
 
 
159
 
160
+ def get_dashboard():
161
+ df = pd.read_sql("SELECT * FROM vehicles", conn)
162
  fig, ax = plt.subplots()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
163
 
164
+ if df.empty:
165
+ ax.text(0.5,0.5,"No data yet",ha="center")
166
+ ax.axis("off")
167
+ return fig
168
 
169
+ df["type"].value_counts().plot(kind="bar", ax=ax)
170
+ ax.set_title("Vehicle Types")
171
+ return fig
172
 
173
+ # ---------------- FEEDBACK ----------------
174
 
175
+ def submit_feedback(result_text, feedback_choice):
176
+ if not result_text:
177
+ return "No result available."
178
 
179
+ cursor.execute(
180
+ "INSERT INTO feedback VALUES (?, ?)",
181
+ (result_text, feedback_choice)
182
+ )
183
+ conn.commit()
184
+ return "Feedback recorded!"
185
 
186
+ def show_accuracy():
187
+ df = pd.read_sql("SELECT * FROM feedback", conn)
188
 
189
+ if df.empty:
190
+ return "No feedback yet."
191
 
192
+ correct = len(df[df["feedback"] == "Correct"])
193
+ total = len(df)
 
 
 
 
 
 
 
 
 
 
 
 
 
194
 
195
+ accuracy = (correct / total) * 100
196
+ return f"Accuracy (User Feedback Based): {accuracy:.2f}%"
 
 
197
 
198
+ # ---------------- CALLBACK ----------------
 
 
 
199
 
200
+ def detect_image(img, threshold):
201
+ if img is None:
202
+ return None, "No image provided"
203
+ output, id2label = make_prediction(img)
204
+ return visualize(img, output, id2label, threshold)
205
 
206
+ # ---------------- UI ----------------
207
+
208
+ with gr.Blocks() as demo:
209
+ gr.Markdown("## Smart Vehicle Classification System")
 
210
 
211
+ slider = gr.Slider(0.3, 1.0, 0.5, label="Confidence Threshold")
212
+
213
+ with gr.Row():
214
+ img_input = gr.Image(type="pil")
215
+ img_output = gr.Plot()
216
+
217
+ result_box = gr.Textbox(label="Detection Result", lines=4)
218
+
219
+ detect_btn = gr.Button("Detect")
220
+ detect_btn.click(
221
+ detect_image,
222
+ inputs=[img_input, slider],
223
+ outputs=[img_output, result_box]
224
  )
225
 
226
+ gr.Markdown("### Feedback")
227
+ feedback_radio = gr.Radio(["Correct", "Incorrect"], label="Prediction correct?")
228
+ feedback_btn = gr.Button("Submit Feedback")
229
+ feedback_msg = gr.Textbox(label="Feedback Status")
230
+
231
+ feedback_btn.click(
232
+ submit_feedback,
233
+ inputs=[result_box, feedback_radio],
234
+ outputs=feedback_msg
235
  )
236
 
237
+ gr.Markdown("### Model Accuracy")
238
+ accuracy_btn = gr.Button("Show Accuracy")
239
+ accuracy_box = gr.Textbox(label="Accuracy")
240
+
241
+ accuracy_btn.click(show_accuracy, outputs=accuracy_box)
242
+
243
+ gr.Markdown("### Dashboard")
244
+ dashboard_plot = gr.Plot()
245
+
246
+ refresh_btn = gr.Button("Refresh Dashboard")
247
+ refresh_btn.click(get_dashboard, outputs=dashboard_plot)
248
+
249
+ demo.launch()