Spaces:
Sleeping
Sleeping
Update processor.py
Browse files- processor.py +57 -198
processor.py
CHANGED
|
@@ -2,26 +2,25 @@
|
|
| 2 |
|
| 3 |
import cv2
|
| 4 |
import numpy as np
|
| 5 |
-
import smtplib
|
| 6 |
-
from email.mime.text import MIMEText
|
| 7 |
-
from email.mime.multipart import MIMEMultipart
|
| 8 |
-
from email.mime.base import MIMEBase
|
| 9 |
-
from email import encoders
|
| 10 |
import os
|
| 11 |
from ultralytics import YOLO
|
| 12 |
from transformers import AutoModel, AutoProcessor
|
| 13 |
from PIL import Image, ImageDraw, ImageFont
|
| 14 |
import re
|
| 15 |
-
import
|
|
|
|
|
|
|
|
|
|
|
|
|
| 16 |
|
| 17 |
-
# Email credentials (
|
| 18 |
-
FROM_EMAIL =
|
| 19 |
-
EMAIL_PASSWORD = "
|
| 20 |
-
TO_EMAIL =
|
| 21 |
SMTP_SERVER = 'smtp.gmail.com'
|
| 22 |
SMTP_PORT = 465
|
| 23 |
|
| 24 |
-
# Arabic dictionary
|
| 25 |
arabic_dict = {
|
| 26 |
"0": "٠", "1": "١", "2": "٢", "3": "٣", "4": "٤", "5": "٥",
|
| 27 |
"6": "٦", "7": "٧", "8": "٨", "9": "٩", "A": "ا", "B": "ب",
|
|
@@ -38,49 +37,44 @@ class_colors = {
|
|
| 38 |
5: (0, 255, 255), # Yellow (Person)
|
| 39 |
}
|
| 40 |
|
| 41 |
-
# Load
|
| 42 |
processor = AutoProcessor.from_pretrained("stepfun-ai/GOT-OCR2_0", trust_remote_code=True)
|
| 43 |
model_ocr = AutoModel.from_pretrained("stepfun-ai/GOT-OCR2_0", trust_remote_code=True).to('cuda')
|
|
|
|
| 44 |
|
| 45 |
-
#
|
| 46 |
-
model = YOLO('yolov8_Medium.pt') # Update the path as needed
|
| 47 |
-
|
| 48 |
-
# Define lane area coordinates (example coordinates)
|
| 49 |
red_lane = np.array([[2,1583],[1,1131],[1828,1141],[1912,1580]], np.int32)
|
| 50 |
|
| 51 |
-
#
|
| 52 |
violations_dict = {}
|
| 53 |
|
| 54 |
-
def filter_license_plate_text(
|
| 55 |
-
|
| 56 |
-
match = re.search(r'(\d{4})\s*([A-Z]{2})',
|
| 57 |
return f"{match.group(1)} {match.group(2)}" if match else None
|
| 58 |
|
| 59 |
-
def convert_to_arabic(
|
| 60 |
-
return "".join(arabic_dict.get(char, char) for char in
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 61 |
|
| 62 |
-
def send_email(license_text, violation_image_path, violation_type):
|
| 63 |
-
# Define the subject and body based on violation type
|
| 64 |
-
if violation_type == 'No Helmet, In Red Lane':
|
| 65 |
-
subject = 'تنبيه مخالفة: عدم ارتداء خوذة ودخول المسار الأيسر'
|
| 66 |
-
body = f"لعدم ارتداء الخوذة ولدخولها المسار الأيسر ({license_text}) تم تغريم دراجة نارية التي تحمل لوحة"
|
| 67 |
-
|
| 68 |
-
elif violation_type == 'In Red Lane':
|
| 69 |
-
subject = 'تنبيه مخالفة: دخول المسار الأيسر'
|
| 70 |
-
body = f"لدخولها المسار الأيسر ({license_text}) تم تغريم دراجة نارية التي تحمل لوحة"
|
| 71 |
-
else:
|
| 72 |
-
violation_type == 'No Helmet'
|
| 73 |
-
subject = 'تنبيه مخالفة: عدم ارتداء خوذة'
|
| 74 |
-
body = f"لعدم ارتداء الخوذة ({license_text}) تم تغريم دراجة نارية التي تحمل لوحة"
|
| 75 |
-
|
| 76 |
-
# Create the email message
|
| 77 |
msg = MIMEMultipart()
|
| 78 |
msg['From'] = FROM_EMAIL
|
| 79 |
msg['To'] = TO_EMAIL
|
| 80 |
-
msg['Subject'] = subject
|
| 81 |
msg.attach(MIMEText(body, 'plain'))
|
| 82 |
|
| 83 |
-
# Attach the violation image
|
| 84 |
if os.path.exists(violation_image_path):
|
| 85 |
with open(violation_image_path, 'rb') as attachment_file:
|
| 86 |
part = MIMEBase('application', 'octet-stream')
|
|
@@ -89,200 +83,65 @@ def send_email(license_text, violation_image_path, violation_type):
|
|
| 89 |
part.add_header('Content-Disposition', f'attachment; filename={os.path.basename(violation_image_path)}')
|
| 90 |
msg.attach(part)
|
| 91 |
|
| 92 |
-
# Send the email using SMTP
|
| 93 |
try:
|
| 94 |
with smtplib.SMTP_SSL(SMTP_SERVER, SMTP_PORT) as server:
|
| 95 |
server.login(FROM_EMAIL, EMAIL_PASSWORD)
|
| 96 |
server.sendmail(FROM_EMAIL, TO_EMAIL, msg.as_string())
|
| 97 |
-
print("Email with attachment sent successfully!")
|
| 98 |
except Exception as e:
|
| 99 |
print(f"Failed to send email: {e}")
|
| 100 |
|
| 101 |
def draw_text_pil(img, text, position, font_path, font_size, color):
|
| 102 |
img_pil = Image.fromarray(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
|
| 103 |
-
|
| 104 |
draw = ImageDraw.Draw(img_pil)
|
| 105 |
-
|
| 106 |
try:
|
| 107 |
font = ImageFont.truetype(font_path, size=font_size)
|
| 108 |
except IOError:
|
| 109 |
-
print(f"Font file not found at {font_path}. Using default font.")
|
| 110 |
font = ImageFont.load_default()
|
| 111 |
-
|
| 112 |
draw.text(position, text, font=font, fill=color)
|
| 113 |
-
|
| 114 |
-
img_np = cv2.cvtColor(np.array(img_pil), cv2.COLOR_RGB2BGR)
|
| 115 |
-
return img_np
|
| 116 |
-
|
| 117 |
-
def process_video(video_path, font_path, violation_image_path='violation.jpg'):
|
| 118 |
-
cap = cv2.VideoCapture(video_path)
|
| 119 |
-
|
| 120 |
-
if not cap.isOpened():
|
| 121 |
-
print("Error opening video file")
|
| 122 |
-
return None
|
| 123 |
-
|
| 124 |
-
fourcc = cv2.VideoWriter_fourcc(*'mp4v')
|
| 125 |
-
output_video_path = 'output_violation.mp4'
|
| 126 |
-
fps = cap.get(cv2.CAP_PROP_FPS)
|
| 127 |
-
width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
|
| 128 |
-
height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
|
| 129 |
-
out = cv2.VideoWriter(output_video_path, fourcc, fps, (width, height))
|
| 130 |
-
|
| 131 |
-
margin_y = 50
|
| 132 |
-
|
| 133 |
-
while cap.isOpened():
|
| 134 |
-
ret, frame = cap.read()
|
| 135 |
-
if not ret:
|
| 136 |
-
break
|
| 137 |
-
|
| 138 |
-
cv2.polylines(frame, [red_lane], isClosed=True, color=(0, 0, 255), thickness=3)
|
| 139 |
-
|
| 140 |
-
results = model.track(frame)
|
| 141 |
-
|
| 142 |
-
for box in results[0].boxes:
|
| 143 |
-
x1, y1, x2, y2 = map(int, box.xyxy[0].cpu().numpy())
|
| 144 |
-
label = model.names[int(box.cls)]
|
| 145 |
-
color = class_colors.get(int(box.cls), (255, 255, 255))
|
| 146 |
-
confidence = box.conf[0].item()
|
| 147 |
-
|
| 148 |
-
helmet_violation = False
|
| 149 |
-
lane_violation = False
|
| 150 |
-
violation_type = []
|
| 151 |
-
|
| 152 |
-
cv2.rectangle(frame, (x1, y1), (x2, y2), color, 3)
|
| 153 |
-
cv2.putText(frame, f'{label}: {confidence:.2f}', (x1, y1 - 10),
|
| 154 |
-
cv2.FONT_HERSHEY_SIMPLEX, 0.6, color, 2)
|
| 155 |
-
|
| 156 |
-
if label == 'MotorbikeDelivery' and confidence >= 0.4:
|
| 157 |
-
motorbike_crop = frame[max(0, y1 - margin_y):y2, x1:x2]
|
| 158 |
-
delivery_center = ((x1 + x2) // 2, y2)
|
| 159 |
-
in_red_lane = cv2.pointPolygonTest(red_lane, delivery_center, False)
|
| 160 |
-
if in_red_lane >= 0:
|
| 161 |
-
lane_violation = True
|
| 162 |
-
violation_type.append("In Red Lane")
|
| 163 |
-
|
| 164 |
-
sub_results = model(motorbike_crop)
|
| 165 |
-
|
| 166 |
-
for result in sub_results[0].boxes:
|
| 167 |
-
sub_x1, sub_y1, sub_x2, sub_y2 = map(int, result.xyxy[0].cpu().numpy())
|
| 168 |
-
sub_label = model.names[int(result.cls)]
|
| 169 |
-
sub_color = (255, 0, 0)
|
| 170 |
-
|
| 171 |
-
cv2.rectangle(motorbike_crop, (sub_x1, sub_y1), (sub_x2, sub_y2), sub_color, 2)
|
| 172 |
-
cv2.putText(motorbike_crop, sub_label, (sub_x1, sub_y1 - 10),
|
| 173 |
-
cv2.FONT_HERSHEY_SIMPLEX, 0.6, sub_color, 2)
|
| 174 |
-
|
| 175 |
-
if sub_label == 'No_Helmet':
|
| 176 |
-
helmet_violation = True
|
| 177 |
-
violation_type.append("No Helmet")
|
| 178 |
-
continue
|
| 179 |
-
if sub_label == 'License_plate':
|
| 180 |
-
license_crop = motorbike_crop[sub_y1:sub_y2, sub_x1:sub_x2]
|
| 181 |
-
|
| 182 |
-
if helmet_violation or lane_violation:
|
| 183 |
-
cv2.imwrite(violation_image_path, frame)
|
| 184 |
-
license_plate_pil = Image.fromarray(cv2.cvtColor(license_crop, cv2.COLOR_BGR2RGB))
|
| 185 |
-
temp_image_path = 'license_plate.png'
|
| 186 |
-
license_plate_pil.save(temp_image_path)
|
| 187 |
-
license_plate_text = model_ocr.chat(processor, temp_image_path, ocr_type='ocr')
|
| 188 |
-
filtered_text = filter_license_plate_text(license_plate_text)
|
| 189 |
-
|
| 190 |
-
if filtered_text:
|
| 191 |
-
if filtered_text not in violations_dict:
|
| 192 |
-
violations_dict[filtered_text] = violation_type
|
| 193 |
-
send_email(filtered_text, violation_image_path, ', '.join(violation_type))
|
| 194 |
-
else:
|
| 195 |
-
current_violations = set(violations_dict[filtered_text])
|
| 196 |
-
new_violations = set(violation_type)
|
| 197 |
-
updated_violations = list(current_violations | new_violations)
|
| 198 |
-
|
| 199 |
-
if updated_violations != violations_dict[filtered_text]:
|
| 200 |
-
violations_dict[filtered_text] = updated_violations
|
| 201 |
-
send_email(filtered_text, violation_image_path, ', '.join(updated_violations))
|
| 202 |
-
|
| 203 |
-
arabic_text = convert_to_arabic(filtered_text)
|
| 204 |
-
frame = draw_text_pil(frame, filtered_text, (x1, y2 + 30), font_path, font_size=30, color=(255, 255, 255))
|
| 205 |
-
frame = draw_text_pil(frame, arabic_text, (x1, y2 + 60), font_path, font_size=30, color=(0, 255, 0))
|
| 206 |
-
|
| 207 |
-
out.write(frame)
|
| 208 |
-
|
| 209 |
-
cap.release()
|
| 210 |
-
out.release()
|
| 211 |
-
return output_video_path
|
| 212 |
-
|
| 213 |
-
def process_image(image_path, font_path, violation_image_path='violation.jpg'):
|
| 214 |
-
frame = cv2.imread(image_path)
|
| 215 |
-
if frame is None:
|
| 216 |
-
print("Error loading image")
|
| 217 |
-
return None
|
| 218 |
-
|
| 219 |
-
cv2.polylines(frame, [red_lane], isClosed=True, color=(0, 0, 255), thickness=3)
|
| 220 |
|
|
|
|
| 221 |
results = model.track(frame)
|
| 222 |
-
|
| 223 |
for box in results[0].boxes:
|
| 224 |
-
x1, y1, x2, y2 = map(int, box.xyxy[0].cpu().numpy())
|
| 225 |
-
label = model.names[int(box.cls)]
|
| 226 |
color = class_colors.get(int(box.cls), (255, 255, 255))
|
| 227 |
confidence = box.conf[0].item()
|
| 228 |
|
| 229 |
-
helmet_violation = False
|
| 230 |
-
lane_violation = False
|
| 231 |
-
violation_type = []
|
| 232 |
-
|
| 233 |
-
cv2.rectangle(frame, (x1, y1), (x2, y2), color, 3)
|
| 234 |
-
cv2.putText(frame, f'{label}: {confidence:.2f}', (x1, y1 - 10),
|
| 235 |
-
cv2.FONT_HERSHEY_SIMPLEX, 0.6, color, 2)
|
| 236 |
-
|
| 237 |
if label == 'MotorbikeDelivery' and confidence >= 0.4:
|
| 238 |
motorbike_crop = frame[max(0, y1 - 50):y2, x1:x2]
|
| 239 |
delivery_center = ((x1 + x2) // 2, y2)
|
| 240 |
in_red_lane = cv2.pointPolygonTest(red_lane, delivery_center, False)
|
|
|
|
| 241 |
if in_red_lane >= 0:
|
| 242 |
-
|
| 243 |
-
violation_type.append("In Red Lane")
|
| 244 |
|
| 245 |
sub_results = model(motorbike_crop)
|
| 246 |
-
|
| 247 |
-
|
| 248 |
-
|
| 249 |
-
sub_label = model.names[int(result.cls)]
|
| 250 |
-
sub_color = (255, 0, 0)
|
| 251 |
-
|
| 252 |
-
cv2.rectangle(motorbike_crop, (sub_x1, sub_y1), (sub_x2, sub_y2), sub_color, 2)
|
| 253 |
-
cv2.putText(motorbike_crop, sub_label, (sub_x1, sub_y1 - 10),
|
| 254 |
-
cv2.FONT_HERSHEY_SIMPLEX, 0.6, sub_color, 2)
|
| 255 |
-
|
| 256 |
if sub_label == 'No_Helmet':
|
| 257 |
-
|
| 258 |
-
|
| 259 |
-
continue
|
| 260 |
-
if sub_label == 'License_plate':
|
| 261 |
license_crop = motorbike_crop[sub_y1:sub_y2, sub_x1:sub_x2]
|
| 262 |
-
|
| 263 |
-
if helmet_violation or lane_violation:
|
| 264 |
cv2.imwrite(violation_image_path, frame)
|
| 265 |
license_plate_pil = Image.fromarray(cv2.cvtColor(license_crop, cv2.COLOR_BGR2RGB))
|
| 266 |
-
|
| 267 |
-
license_plate_pil.save(temp_image_path)
|
| 268 |
license_plate_text = model_ocr.chat(processor, temp_image_path, ocr_type='ocr')
|
| 269 |
filtered_text = filter_license_plate_text(license_plate_text)
|
| 270 |
-
|
| 271 |
if filtered_text:
|
| 272 |
if filtered_text not in violations_dict:
|
| 273 |
-
violations_dict[filtered_text] =
|
| 274 |
-
send_email(filtered_text, violation_image_path, ', '.join(
|
| 275 |
else:
|
| 276 |
-
|
| 277 |
-
|
| 278 |
-
|
| 279 |
-
|
| 280 |
-
|
| 281 |
-
|
| 282 |
-
send_email(filtered_text, violation_image_path, ', '.join(updated_violations))
|
| 283 |
-
|
| 284 |
arabic_text = convert_to_arabic(filtered_text)
|
| 285 |
-
frame = draw_text_pil(frame, filtered_text, (x1, y2 + 30), font_path,
|
| 286 |
-
frame = draw_text_pil(frame, arabic_text, (x1, y2 + 60), font_path,
|
| 287 |
-
|
| 288 |
-
return frame
|
|
|
|
| 2 |
|
| 3 |
import cv2
|
| 4 |
import numpy as np
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 5 |
import os
|
| 6 |
from ultralytics import YOLO
|
| 7 |
from transformers import AutoModel, AutoProcessor
|
| 8 |
from PIL import Image, ImageDraw, ImageFont
|
| 9 |
import re
|
| 10 |
+
import smtplib
|
| 11 |
+
from email.mime.text import MIMEText
|
| 12 |
+
from email.mime.multipart import MIMEMultipart
|
| 13 |
+
from email.mime.base import MIMEBase
|
| 14 |
+
from email import encoders
|
| 15 |
|
| 16 |
+
# Email credentials (Use environment variables for security)
|
| 17 |
+
FROM_EMAIL = os.getenv("FROM_EMAIL")
|
| 18 |
+
EMAIL_PASSWORD = os.getenv("EMAIL_PASSWORD")
|
| 19 |
+
TO_EMAIL = os.getenv("TO_EMAIL")
|
| 20 |
SMTP_SERVER = 'smtp.gmail.com'
|
| 21 |
SMTP_PORT = 465
|
| 22 |
|
| 23 |
+
# Arabic dictionary
|
| 24 |
arabic_dict = {
|
| 25 |
"0": "٠", "1": "١", "2": "٢", "3": "٣", "4": "٤", "5": "٥",
|
| 26 |
"6": "٦", "7": "٧", "8": "٨", "9": "٩", "A": "ا", "B": "ب",
|
|
|
|
| 37 |
5: (0, 255, 255), # Yellow (Person)
|
| 38 |
}
|
| 39 |
|
| 40 |
+
# Load models
|
| 41 |
processor = AutoProcessor.from_pretrained("stepfun-ai/GOT-OCR2_0", trust_remote_code=True)
|
| 42 |
model_ocr = AutoModel.from_pretrained("stepfun-ai/GOT-OCR2_0", trust_remote_code=True).to('cuda')
|
| 43 |
+
model = YOLO('yolov8_Medium.pt') # Update path as needed
|
| 44 |
|
| 45 |
+
# Define lane area
|
|
|
|
|
|
|
|
|
|
| 46 |
red_lane = np.array([[2,1583],[1,1131],[1828,1141],[1912,1580]], np.int32)
|
| 47 |
|
| 48 |
+
# Violation tracking
|
| 49 |
violations_dict = {}
|
| 50 |
|
| 51 |
+
def filter_license_plate_text(text):
|
| 52 |
+
text = re.sub(r'[^A-Z0-9]+', "", text)
|
| 53 |
+
match = re.search(r'(\d{4})\s*([A-Z]{2})', text)
|
| 54 |
return f"{match.group(1)} {match.group(2)}" if match else None
|
| 55 |
|
| 56 |
+
def convert_to_arabic(text):
|
| 57 |
+
return "".join(arabic_dict.get(char, char) for char in text)
|
| 58 |
+
|
| 59 |
+
def send_email(license_text, violation_image_path, violation_type):
|
| 60 |
+
subject = {
|
| 61 |
+
'No Helmet, In Red Lane': 'تنبيه مخالفة: عدم ارتداء خوذة ودخول المسار الأيسر',
|
| 62 |
+
'In Red Lane': 'تنبيه مخالفة: دخول المسار الأيسر',
|
| 63 |
+
'No Helmet': 'تنبيه مخالفة: عدم ارتداء خوذة'
|
| 64 |
+
}.get(violation_type, 'تنبيه مخالفة')
|
| 65 |
+
|
| 66 |
+
body = {
|
| 67 |
+
'No Helmet, In Red Lane': f"لعدم ارتداء الخوذة ولدخولها المسار الأيسر ({license_text}) تم تغريم دراجة نارية التي تحمل لوحة",
|
| 68 |
+
'In Red Lane': f"لدخولها المسار الأيسر ({license_text}) تم تغريم دراجة نارية التي تحمل لوحة",
|
| 69 |
+
'No Helmet': f"لعدم ارتداء الخوذة ({license_text}) تم تغريم دراجة نارية التي تحمل لوحة"
|
| 70 |
+
}.get(violation_type, f"تم تغريم دراجة نارية التي تحمل لوحة ({license_text})")
|
| 71 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 72 |
msg = MIMEMultipart()
|
| 73 |
msg['From'] = FROM_EMAIL
|
| 74 |
msg['To'] = TO_EMAIL
|
| 75 |
+
msg['Subject'] = subject
|
| 76 |
msg.attach(MIMEText(body, 'plain'))
|
| 77 |
|
|
|
|
| 78 |
if os.path.exists(violation_image_path):
|
| 79 |
with open(violation_image_path, 'rb') as attachment_file:
|
| 80 |
part = MIMEBase('application', 'octet-stream')
|
|
|
|
| 83 |
part.add_header('Content-Disposition', f'attachment; filename={os.path.basename(violation_image_path)}')
|
| 84 |
msg.attach(part)
|
| 85 |
|
|
|
|
| 86 |
try:
|
| 87 |
with smtplib.SMTP_SSL(SMTP_SERVER, SMTP_PORT) as server:
|
| 88 |
server.login(FROM_EMAIL, EMAIL_PASSWORD)
|
| 89 |
server.sendmail(FROM_EMAIL, TO_EMAIL, msg.as_string())
|
|
|
|
| 90 |
except Exception as e:
|
| 91 |
print(f"Failed to send email: {e}")
|
| 92 |
|
| 93 |
def draw_text_pil(img, text, position, font_path, font_size, color):
|
| 94 |
img_pil = Image.fromarray(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
|
|
|
|
| 95 |
draw = ImageDraw.Draw(img_pil)
|
|
|
|
| 96 |
try:
|
| 97 |
font = ImageFont.truetype(font_path, size=font_size)
|
| 98 |
except IOError:
|
|
|
|
| 99 |
font = ImageFont.load_default()
|
|
|
|
| 100 |
draw.text(position, text, font=font, fill=color)
|
| 101 |
+
return cv2.cvtColor(np.array(img_pil), cv2.COLOR_RGB2BGR)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 102 |
|
| 103 |
+
def process_frame(frame, font_path, violation_image_path='violation.jpg'):
|
| 104 |
results = model.track(frame)
|
|
|
|
| 105 |
for box in results[0].boxes:
|
| 106 |
+
x1, y1, x2, y2 = map(int, box.xyxy[0].cpu().numpy())
|
| 107 |
+
label = model.names[int(box.cls)]
|
| 108 |
color = class_colors.get(int(box.cls), (255, 255, 255))
|
| 109 |
confidence = box.conf[0].item()
|
| 110 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 111 |
if label == 'MotorbikeDelivery' and confidence >= 0.4:
|
| 112 |
motorbike_crop = frame[max(0, y1 - 50):y2, x1:x2]
|
| 113 |
delivery_center = ((x1 + x2) // 2, y2)
|
| 114 |
in_red_lane = cv2.pointPolygonTest(red_lane, delivery_center, False)
|
| 115 |
+
violation_types = []
|
| 116 |
if in_red_lane >= 0:
|
| 117 |
+
violation_types.append("In Red Lane")
|
|
|
|
| 118 |
|
| 119 |
sub_results = model(motorbike_crop)
|
| 120 |
+
for sub_box in sub_results[0].boxes:
|
| 121 |
+
sub_x1, sub_y1, sub_x2, sub_y2 = map(int, sub_box.xyxy[0].cpu().numpy())
|
| 122 |
+
sub_label = model.names[int(sub_box.cls)]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 123 |
if sub_label == 'No_Helmet':
|
| 124 |
+
violation_types.append("No Helmet")
|
| 125 |
+
elif sub_label == 'License_plate':
|
|
|
|
|
|
|
| 126 |
license_crop = motorbike_crop[sub_y1:sub_y2, sub_x1:sub_x2]
|
| 127 |
+
if violation_types:
|
|
|
|
| 128 |
cv2.imwrite(violation_image_path, frame)
|
| 129 |
license_plate_pil = Image.fromarray(cv2.cvtColor(license_crop, cv2.COLOR_BGR2RGB))
|
| 130 |
+
license_plate_pil.save('license_plate.png')
|
|
|
|
| 131 |
license_plate_text = model_ocr.chat(processor, temp_image_path, ocr_type='ocr')
|
| 132 |
filtered_text = filter_license_plate_text(license_plate_text)
|
|
|
|
| 133 |
if filtered_text:
|
| 134 |
if filtered_text not in violations_dict:
|
| 135 |
+
violations_dict[filtered_text] = violation_types
|
| 136 |
+
send_email(filtered_text, violation_image_path, ', '.join(violation_types))
|
| 137 |
else:
|
| 138 |
+
current = set(violations_dict[filtered_text])
|
| 139 |
+
new = set(violation_types)
|
| 140 |
+
updated = current | new
|
| 141 |
+
if updated != current:
|
| 142 |
+
violations_dict[filtered_text] = list(updated)
|
| 143 |
+
send_email(filtered_text, violation_image_path, ', '.join(updated))
|
|
|
|
|
|
|
| 144 |
arabic_text = convert_to_arabic(filtered_text)
|
| 145 |
+
frame = draw_text_pil(frame, filtered_text, (x1, y2 + 30), font_path, 30, (255, 255, 255))
|
| 146 |
+
frame = draw_text_pil(frame, arabic_text, (x1, y2 + 60), font_path, 30, (0, 255, 0))
|
| 147 |
+
return frame
|
|
|