commit aa90d3a455868e9eafc48c0c22e591a9f56b133c Author: kicap Date: Wed Jul 16 07:13:43 2025 +0800 first commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..dbe1273 --- /dev/null +++ b/.gitignore @@ -0,0 +1,21 @@ +# Virtual environments +env/ +venv/ +.venv/ + +# Python cache +__pycache__/ +*.py[cod] +*.pyo + +# Distribution / packaging +build/ +dist/ +*.egg-info/ + +# IDEs/editors (optional but common) +.vscode/ +.idea/ + +# Jupyter Notebook checkpoints (optional) +.ipynb_checkpoints/ diff --git a/app.py b/app.py new file mode 100644 index 0000000..878c5f1 --- /dev/null +++ b/app.py @@ -0,0 +1,110 @@ +import cv2 +import pymysql +from datetime import datetime +from ultralytics import YOLO +from deep_sort_realtime.deepsort_tracker import DeepSort + +# ------------------------------- +# CONFIG +# ------------------------------- +RTSP_URL = "pagi.mp4" +LINE_A = 200 +LINE_B = 500 + +DB_CONFIG = { + 'host': 'localhost', + 'user': 'root', + 'password': '', + 'database': 'db_traffic2' +} + +# ------------------------------- +# Setup +# ------------------------------- +cap = cv2.VideoCapture(RTSP_URL) +model = YOLO("yolov8n.pt") # Downloads automatically +tracker = DeepSort(max_age=30) + +# MySQL Connection +db = pymysql.connect(**DB_CONFIG) +cursor = db.cursor() + +tracked_ids = {} # {track_id: {'y': prev_y, 'line': 'A' or 'B'}} + +while cap.isOpened(): + ret, frame = cap.read() + if not ret: + print("RTSP stream ended or cannot be read.") + break + + # ------------------------------- + # YOLO Detection + # ------------------------------- + results = model(frame, verbose=False)[0] + detections = [] + + for box in results.boxes: + x1, y1, x2, y2 = box.xyxy[0] + conf = float(box.conf[0]) + cls_id = int(box.cls[0]) + class_name = model.names[cls_id] + + if class_name in ["car", "bus", "truck", "motorbike"]: + bbox = [x1.item(), y1.item(), x2.item() - x1.item(), y2.item() - y1.item()] + detections.append((bbox, conf, class_name)) + + # ------------------------------- + # DeepSORT Tracking + # ------------------------------- + tracks = tracker.update_tracks(detections, frame=frame) + + for track in tracks: + if not track.is_confirmed(): + continue + + track_id = track.track_id + ltrb = track.to_ltrb() + x1, y1, x2, y2 = map(int, ltrb) + center_y = (y1 + y2) // 2 + + prev = tracked_ids.get(track_id) + tracked_ids[track_id] = {'y': center_y} + + if prev: + prev_y = prev['y'] + + # Determine direction and line crossing + if prev_y < LINE_A and center_y >= LINE_A: + direction = 'down' + now = datetime.now() + elif prev_y > LINE_B and center_y <= LINE_B: + direction = 'up' + now = datetime.now() + else: + continue + print(f"[{now}] Vehicle {track_id} crossed {direction}") + + # Save to DB + sql = "INSERT INTO vehicle_crossings (vehicle_id, direction, crossing_time) VALUES (%s, %s, %s)" + cursor.execute(sql, (f"vehicle_{track_id}", direction, now)) + db.commit() + + # Draw box and label + cv2.rectangle(frame, (x1, y1), (x2, y2), (0, 255, 0), 2) + cv2.putText(frame, f'ID {track_id}', (x1, y1 - 10), + cv2.FONT_HERSHEY_SIMPLEX, 0.6, (255, 255, 255), 2) + + # Draw reference lines + cv2.line(frame, (0, LINE_A), (frame.shape[1], LINE_A), (255, 0, 0), 2) + cv2.line(frame, (0, LINE_B), (frame.shape[1], LINE_B), (0, 0, 255), 2) + + # Show frame + cv2.imshow("YOLO + DeepSORT", frame) + if cv2.waitKey(1) == 27: # ESC to quit + break + +# Cleanup +cap.release() +cv2.destroyAllWindows() +cursor.close() +db.close() diff --git a/app2.py b/app2.py new file mode 100644 index 0000000..78ed910 --- /dev/null +++ b/app2.py @@ -0,0 +1,131 @@ +import cv2 +import numpy as np +import pymysql +from datetime import datetime + +# Database connection +conn = pymysql.connect( + host='localhost', + user='root', + password='', + database='db_traffic2' +) +cursor = conn.cursor() + +# RTSP stream or test video +cap = cv2.VideoCapture('pagi.mp4') # Change to RTSP URL if needed + +# Resize ratio +ratio = 0.5 +ret, frame = cap.read() +image = cv2.resize(frame, (0, 0), None, ratio, ratio) +width2, height2, channels = image.shape + +# Background subtractor +fgbg = cv2.createBackgroundSubtractorMOG2() + +# Tracking + speed +vehicle_id_counter = 0 +tracker_dict = {} +speed_line_y1 = 150 +speed_line_y2 = 200 +pixel_distance = abs(speed_line_y2 - speed_line_y1) +fps = cap.get(cv2.CAP_PROP_FPS) or 60 # fallback default + +# Main loop +while True: + ret, frame = cap.read() + if not ret: + break + + image = cv2.resize(frame, (0, 0), None, ratio, ratio) + gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) + fgmask = fgbg.apply(gray) + + kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5, 5)) + closing = cv2.morphologyEx(fgmask, cv2.MORPH_CLOSE, kernel) + opening = cv2.morphologyEx(closing, cv2.MORPH_OPEN, kernel) + dilation = cv2.dilate(opening, kernel) + _, bins = cv2.threshold(dilation, 220, 255, cv2.THRESH_BINARY) + + contours, _ = cv2.findContours(bins, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)[-2:] + hull = [cv2.convexHull(c) for c in contours] + cv2.drawContours(image, hull, -1, (0, 255, 0), 2) + + min_area = 400 + max_area = 40000 + + for cnt in contours: + area = cv2.contourArea(cnt) + if min_area < area < max_area: + M = cv2.moments(cnt) + if M['m00'] == 0: + continue + cx = int(M['m10'] / M['m00']) + cy = int(M['m01'] / M['m00']) + + x, y, w, h = cv2.boundingRect(cnt) + cv2.rectangle(image, (x, y), (x + w, y + h), (255, 0, 0), 2) + cv2.drawMarker(image, (cx, cy), (0, 0, 255), cv2.MARKER_CROSS, 10, 1) + + matched_id = None + for vid, info in tracker_dict.items(): + old_cx, old_cy = info['pos'] + if abs(cx - old_cx) < 30 and abs(cy - old_cy) < 30: + matched_id = vid + break + + if matched_id is None: + matched_id = vehicle_id_counter + vehicle_id_counter += 1 + tracker_dict[matched_id] = {'pos': (cx, cy), 't1': None, 't2': None, 'logged': False} + else: + tracker_dict[matched_id]['pos'] = (cx, cy) + + vehicle = tracker_dict[matched_id] + if not vehicle['t1'] and cy >= speed_line_y1: + vehicle['t1'] = datetime.now() + elif not vehicle['t2'] and cy >= speed_line_y2: + vehicle['t2'] = datetime.now() + + if vehicle['t1'] and vehicle['t2'] and not vehicle['logged']: + delta_time = (vehicle['t2'] - vehicle['t1']).total_seconds() + if delta_time > 0: + meters = 1 # realistic estimated distance in meters + speed_kmh = (meters / delta_time) * 3.6 + + print(f"ID {matched_id} SPEED: {speed_kmh:.2f} km/h") + + # Log to database + cursor.execute( + "INSERT INTO vehicle_log (vehicle_id, direction, timestamp, speed) VALUES (%s, %s, %s, %s)", + (matched_id, 'down', datetime.now(), round(speed_kmh, 2)) + ) + conn.commit() + vehicle['logged'] = True + + # Show ID and speed + cv2.putText(image, f"ID:{matched_id}", (x, y - 5), + cv2.FONT_HERSHEY_SIMPLEX, 0.4, (0, 255, 255), 1) + + if vehicle['t1'] and vehicle['t2']: + delta_time = (vehicle['t2'] - vehicle['t1']).total_seconds() + if delta_time > 0: + speed_kmh = (7.5 / delta_time) * 3.6 + cv2.putText(image, f"{speed_kmh:.1f} km/h", (x, y + h + 15), + cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 255, 0), 2) + + # Draw full-width lines + cv2.line(image, (0, speed_line_y1), (width2, speed_line_y1), (0, 255, 255), 2) + cv2.line(image, (0, speed_line_y2), (width2, speed_line_y2), (255, 0, 255), 2) + + # Display window + cv2.imshow("Vehicle Detection", image) + if cv2.waitKey(1) & 0xFF == 27: # ESC to quit + break + +# Cleanup +cap.release() +cursor.close() +conn.close() +cv2.destroyAllWindows() diff --git a/app3.py b/app3.py new file mode 100644 index 0000000..e5a7e08 --- /dev/null +++ b/app3.py @@ -0,0 +1,131 @@ +import cv2 +import numpy as np +import pymysql +from datetime import datetime + +# Database connection +conn = pymysql.connect( + host='localhost', + user='root', + password='', + database='db_traffic2' +) +cursor = conn.cursor() + +# RTSP stream or test video +cap = cv2.VideoCapture('pagi.mp4') # Replace with RTSP URL when needed + +# Get original width and height +ret, frame = cap.read() +if not ret: + print("Failed to read from video source.") + exit() + +height2, width2, channels = frame.shape + +# Background subtractor +fgbg = cv2.createBackgroundSubtractorMOG2() + +# Vehicle tracking and speed +vehicle_id_counter = 0 +tracker_dict = {} +speed_line_y1 = 225 +speed_line_y2 = 365 +pixel_distance = abs(speed_line_y2 - speed_line_y1) +fps = cap.get(cv2.CAP_PROP_FPS) or 60 # fallback + +meters_travel_pixel = 0.2 + +while True: + ret, frame = cap.read() + if not ret: + break + + gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) + fgmask = fgbg.apply(gray) + + kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5, 5)) + closing = cv2.morphologyEx(fgmask, cv2.MORPH_CLOSE, kernel) + opening = cv2.morphologyEx(closing, cv2.MORPH_OPEN, kernel) + dilation = cv2.dilate(opening, kernel) + _, bins = cv2.threshold(dilation, 220, 255, cv2.THRESH_BINARY) + + contours, _ = cv2.findContours(bins, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)[-2:] + hull = [cv2.convexHull(c) for c in contours] + cv2.drawContours(frame, hull, -1, (0, 255, 0), 2) + + min_area = 400 + max_area = 40000 + + for cnt in contours: + area = cv2.contourArea(cnt) + if min_area < area < max_area: + M = cv2.moments(cnt) + if M['m00'] == 0: + continue + cx = int(M['m10'] / M['m00']) + cy = int(M['m01'] / M['m00']) + + x, y, w, h = cv2.boundingRect(cnt) + cv2.rectangle(frame, (x, y), (x + w, y + h), (255, 0, 0), 2) + cv2.drawMarker(frame, (cx, cy), (0, 0, 255), cv2.MARKER_CROSS, 10, 1) + + matched_id = None + for vid, info in tracker_dict.items(): + old_cx, old_cy = info['pos'] + if abs(cx - old_cx) < 30 and abs(cy - old_cy) < 30: + matched_id = vid + break + + if matched_id is None: + matched_id = vehicle_id_counter + vehicle_id_counter += 1 + tracker_dict[matched_id] = {'pos': (cx, cy), 't1': None, 't2': None, 'logged': False} + else: + tracker_dict[matched_id]['pos'] = (cx, cy) + + vehicle = tracker_dict[matched_id] + if not vehicle['t1'] and cy >= speed_line_y1: + vehicle['t1'] = datetime.now() + elif not vehicle['t2'] and cy >= speed_line_y2: + vehicle['t2'] = datetime.now() + + if vehicle['t1'] and vehicle['t2'] and not vehicle['logged']: + delta_time = (vehicle['t2'] - vehicle['t1']).total_seconds() + if delta_time > 0: + # realistic estimation + speed_kmh = (meters_travel_pixel / delta_time) * 3.6 + + print(f"ID {matched_id} SPEED: {speed_kmh:.2f} km/h") + + # Insert into DB + cursor.execute( + "INSERT INTO vehicle_log (vehicle_id, direction, timestamp, speed) VALUES (%s, %s, %s, %s)", + (matched_id, 'down', datetime.now(), round(speed_kmh, 2)) + ) + conn.commit() + vehicle['logged'] = True + + # Show ID and speed + cv2.putText(frame, f"ID:{matched_id}", (x, y - 5), + cv2.FONT_HERSHEY_SIMPLEX, 0.4, (0, 255, 255), 1) + + if vehicle['t1'] and vehicle['t2']: + delta_time = (vehicle['t2'] - vehicle['t1']).total_seconds() + if delta_time > 0: + speed_kmh = (meters_travel_pixel / delta_time) * 3.6 + cv2.putText(frame, f"{speed_kmh:.1f} km/h", (x, y + h + 15), + cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 255, 0), 2) + + # Draw full-width lines + cv2.line(frame, (0, speed_line_y1), (width2, speed_line_y1), (0, 255, 255), 2) + cv2.line(frame, (0, speed_line_y2), (width2, speed_line_y2), (255, 0, 255), 2) + + cv2.imshow("Vehicle Detection", frame) + if cv2.waitKey(1) & 0xFF == 27: + break + +cap.release() +cursor.close() +conn.close() +cv2.destroyAllWindows() diff --git a/app4.py b/app4.py new file mode 100644 index 0000000..4925eb3 --- /dev/null +++ b/app4.py @@ -0,0 +1,142 @@ +import cv2 +import numpy as np +import pymysql +from datetime import datetime + +# Database connection +conn = pymysql.connect( + host='localhost', + user='root', + password='', + database='db_traffic2' +) +cursor = conn.cursor() + +# RTSP stream or test video +# cap = cv2.VideoCapture('pagi.mp4') # Replace with RTSP URL when needed +cap = cv2.VideoCapture('rtsp://20.20.20.33:8554/') # Replace with RTSP URL when needed + +# Get original width and height +ret, frame = cap.read() +if not ret: + print("Failed to read from video source.") + exit() + +height2, width2, channels = frame.shape + +# Background subtractor +fgbg = cv2.createBackgroundSubtractorMOG2() + +# Vehicle tracking and speed +vehicle_id_counter = 0 +tracker_dict = {} + +# Line positions (adjust as needed) +speed_line_y1 = 255 +speed_line_y2 = 390 +pixel_distance = abs(speed_line_y2 - speed_line_y1) + +# Real-world distance between lines in meters (adjust based on real road) +real_world_distance_m = 0.25 # ← adjust if your line spacing is closer/farther + +while True: + ret, frame = cap.read() + if not ret: + break + + gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) + fgmask = fgbg.apply(gray) + + kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5, 5)) + closing = cv2.morphologyEx(fgmask, cv2.MORPH_CLOSE, kernel) + opening = cv2.morphologyEx(closing, cv2.MORPH_OPEN, kernel) + dilation = cv2.dilate(opening, kernel) + _, bins = cv2.threshold(dilation, 220, 255, cv2.THRESH_BINARY) + + contours, _ = cv2.findContours(bins, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)[-2:] + hull = [cv2.convexHull(c) for c in contours] + cv2.drawContours(frame, hull, -1, (0, 255, 0), 2) + + min_area = 400 + max_area = 40000 + + for cnt in contours: + area = cv2.contourArea(cnt) + if min_area < area < max_area: + M = cv2.moments(cnt) + if M['m00'] == 0: + continue + cx = int(M['m10'] / M['m00']) + cy = int(M['m01'] / M['m00']) + + x, y, w, h = cv2.boundingRect(cnt) + cv2.rectangle(frame, (x, y), (x + w, y + h), (255, 0, 0), 2) + cv2.drawMarker(frame, (cx, cy), (0, 0, 255), cv2.MARKER_CROSS, 10, 1) + + matched_id = None + for vid, info in tracker_dict.items(): + old_cx, old_cy = info['pos'] + if abs(cx - old_cx) < 30 and abs(cy - old_cy) < 30: + matched_id = vid + break + + if matched_id is None: + matched_id = vehicle_id_counter + vehicle_id_counter += 1 + tracker_dict[matched_id] = {'pos': (cx, cy), 't1': None, 't2': None, 'logged': False} + else: + tracker_dict[matched_id]['pos'] = (cx, cy) + + vehicle = tracker_dict[matched_id] + if not vehicle['t1'] and cy >= speed_line_y1: + vehicle['t1'] = datetime.now() + elif not vehicle['t2'] and cy >= speed_line_y2: + vehicle['t2'] = datetime.now() + + if vehicle['t1'] and vehicle['t2'] and not vehicle['logged']: + delta_time = (vehicle['t2'] - vehicle['t1']).total_seconds() + if delta_time > 0: + speed_kmh = (real_world_distance_m / delta_time) * 3.6 + + if speed_kmh >= 10: + print(f"ID {matched_id} SPEED: {speed_kmh:.2f} km/h") + + # Insert into DB only if speed ≥ 10 + cursor.execute( + "INSERT INTO vehicle_log (vehicle_id, direction, timestamp, speed) VALUES (%s, %s, %s, %s)", + (matched_id, 'down', datetime.now(), round(speed_kmh, 2)) + ) + conn.commit() + else: + print(f"ID {matched_id} IGNORED (too slow): {speed_kmh:.2f} km/h") + + + + vehicle['logged'] = True + + # Display ID + cv2.putText(frame, f"ID:{matched_id}", (x, y - 5), + cv2.FONT_HERSHEY_SIMPLEX, 0.4, (0, 255, 255), 1) + + # Show speed on screen + if vehicle['t1'] and vehicle['t2']: + delta_time = (vehicle['t2'] - vehicle['t1']).total_seconds() + if delta_time > 0: + speed_kmh = (real_world_distance_m / delta_time) * 3.6 + cv2.putText(frame, f"{speed_kmh:.1f} km/h", (x, y + h + 15), + cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 255, 0), 2) + + # Draw lines + cv2.line(frame, (0, speed_line_y1), (width2, speed_line_y1), (0, 255, 255), 2) + cv2.line(frame, (0, speed_line_y2), (width2, speed_line_y2), (255, 0, 255), 2) + + # Show output + cv2.imshow("Vehicle Detection", frame) + if cv2.waitKey(1) & 0xFF == 27: + break + +# Cleanup +cap.release() +cursor.close() +conn.close() +cv2.destroyAllWindows() diff --git a/app5.py b/app5.py new file mode 100644 index 0000000..212a414 --- /dev/null +++ b/app5.py @@ -0,0 +1,146 @@ +import cv2 +import numpy as np +import pymysql +from datetime import datetime + +# DB Connection +conn = pymysql.connect( + host='localhost', + user='root', + password='', + database='db_traffic2' +) +cursor = conn.cursor() + +# RTSP or video +cap = cv2.VideoCapture('rtsp://20.20.20.33:8554/') +ret, frame = cap.read() +if not ret: + print("Failed to read from source.") + exit() + +height2, width2, channels = frame.shape + +fgbg = cv2.createBackgroundSubtractorMOG2() + +vehicle_id_counter = 0 +tracker_dict = {} + +# Speed lines +speed_line_y1 = 275 +speed_line_y2 = 370 +real_world_distance_m = 0.25 +min_speed_kmh = 10 # Threshold + +# Track last counted vehicle IDs to avoid spamming the total_vehicle table +last_vehicle_ids_in_zone = set() + +while True: + ret, frame = cap.read() + if not ret: + break + + gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) + fgmask = fgbg.apply(gray) + + kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5, 5)) + closing = cv2.morphologyEx(fgmask, cv2.MORPH_CLOSE, kernel) + opening = cv2.morphologyEx(closing, cv2.MORPH_OPEN, kernel) + dilation = cv2.dilate(opening, kernel) + _, bins = cv2.threshold(dilation, 220, 255, cv2.THRESH_BINARY) + + contours, _ = cv2.findContours(bins, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)[-2:] + cv2.drawContours(frame, [cv2.convexHull(c) for c in contours], -1, (0, 255, 0), 2) + + min_area = 400 + max_area = 40000 + + vehicle_ids_in_zone = set() + + for cnt in contours: + area = cv2.contourArea(cnt) + if not (min_area < area < max_area): + continue + + M = cv2.moments(cnt) + if M['m00'] == 0: + continue + cx = int(M['m10'] / M['m00']) + cy = int(M['m01'] / M['m00']) + + x, y, w, h = cv2.boundingRect(cnt) + cv2.rectangle(frame, (x, y), (x + w, y + h), (255, 0, 0), 2) + cv2.drawMarker(frame, (cx, cy), (0, 0, 255), cv2.MARKER_CROSS, 10, 1) + + matched_id = None + for vid, info in tracker_dict.items(): + old_cx, old_cy = info['pos'] + if abs(cx - old_cx) < 30 and abs(cy - old_cy) < 30: + matched_id = vid + break + + if matched_id is None: + matched_id = vehicle_id_counter + vehicle_id_counter += 1 + tracker_dict[matched_id] = {'pos': (cx, cy), 't1': None, 't2': None, 'logged': False} + else: + tracker_dict[matched_id]['pos'] = (cx, cy) + + vehicle = tracker_dict[matched_id] + if not vehicle['t1'] and cy >= speed_line_y1: + vehicle['t1'] = datetime.now() + elif not vehicle['t2'] and cy >= speed_line_y2: + vehicle['t2'] = datetime.now() + + # Speed check and log + if vehicle['t1'] and vehicle['t2'] and not vehicle['logged']: + delta_time = (vehicle['t2'] - vehicle['t1']).total_seconds() + if delta_time > 0: + speed_kmh = (real_world_distance_m / delta_time) * 3.6 + if speed_kmh >= min_speed_kmh: + print(f"ID {matched_id} SPEED: {speed_kmh:.2f} km/h") + cursor.execute( + "INSERT INTO vehicle_log (vehicle_id, direction, timestamp, speed) VALUES (%s, %s, %s, %s)", + (matched_id, 'down', datetime.now(), round(speed_kmh, 2)) + ) + conn.commit() + else: + print(f"ID {matched_id} IGNORED (too slow): {speed_kmh:.2f} km/h") + vehicle['logged'] = True + + # Labeling + cv2.putText(frame, f"ID:{matched_id}", (x, y - 5), + cv2.FONT_HERSHEY_SIMPLEX, 0.4, (0, 255, 255), 1) + + if vehicle['t1'] and vehicle['t2']: + delta_time = (vehicle['t2'] - vehicle['t1']).total_seconds() + if delta_time > 0: + speed_kmh = (real_world_distance_m / delta_time) * 3.6 + cv2.putText(frame, f"{speed_kmh:.1f} km/h", (x, y + h + 15), + cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 255, 0), 2) + + # Check if vehicle is between the lines + if speed_line_y1 <= cy <= speed_line_y2: + vehicle_ids_in_zone.add(matched_id) + + # Save count only if it changes + if vehicle_ids_in_zone != last_vehicle_ids_in_zone: + last_vehicle_ids_in_zone = vehicle_ids_in_zone.copy() + count = len(vehicle_ids_in_zone) + cursor.execute("INSERT INTO total_vehicle (count, timestamp) VALUES (%s, %s)", (count, datetime.now())) + conn.commit() + print(f"🚗 Vehicles in zone: {count}") + + # Draw detection lines + cv2.line(frame, (0, speed_line_y1), (width2, speed_line_y1), (0, 255, 255), 2) + cv2.line(frame, (0, speed_line_y2), (width2, speed_line_y2), (255, 0, 255), 2) + + cv2.imshow("Vehicle Detection", frame) + if cv2.waitKey(1) & 0xFF == 27: + break + +# Cleanup +cap.release() +cursor.close() +conn.close() +cv2.destroyAllWindows() diff --git a/app6.py b/app6.py new file mode 100644 index 0000000..0ad8716 --- /dev/null +++ b/app6.py @@ -0,0 +1,164 @@ +import cv2 +import numpy as np +import pymysql +from datetime import datetime + +# DB Connection +conn = pymysql.connect( + host='localhost', + user='root', + password='', + database='db_traffic2' +) +cursor = conn.cursor() + +# RTSP or video +cap = cv2.VideoCapture('rtsp://20.20.20.33:8554/') +ret, frame = cap.read() +if not ret: + print("Failed to read from source.") + exit() + +height2, width2, channels = frame.shape + +fgbg = cv2.createBackgroundSubtractorMOG2() + +vehicle_id_counter = 0 +tracker_dict = {} + +# Speed lines +speed_line_y1 = 230 +speed_line_y2 = 340 +real_world_distance_m = 0.25 # Distance between lines in meters +min_speed_kmh = 10 # Speed threshold + +last_vehicle_ids_in_zone = set() + +while True: + ret, frame = cap.read() + if not ret: + break + + gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) + fgmask = fgbg.apply(gray) + + kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5, 5)) + closing = cv2.morphologyEx(fgmask, cv2.MORPH_CLOSE, kernel) + opening = cv2.morphologyEx(closing, cv2.MORPH_OPEN, kernel) + dilation = cv2.dilate(opening, kernel) + _, bins = cv2.threshold(dilation, 220, 255, cv2.THRESH_BINARY) + + contours, _ = cv2.findContours(bins, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)[-2:] + cv2.drawContours(frame, [cv2.convexHull(c) for c in contours], -1, (0, 255, 0), 2) + + min_area = 400 + max_area = 40000 + + vehicle_ids_in_zone = set() + + for cnt in contours: + area = cv2.contourArea(cnt) + if not (min_area < area < max_area): + continue + + M = cv2.moments(cnt) + if M['m00'] == 0: + continue + cx = int(M['m10'] / M['m00']) + cy = int(M['m01'] / M['m00']) + + x, y, w, h = cv2.boundingRect(cnt) + cv2.rectangle(frame, (x, y), (x + w, y + h), (255, 0, 0), 2) + cv2.drawMarker(frame, (cx, cy), (0, 0, 255), cv2.MARKER_CROSS, 10, 1) + + matched_id = None + for vid, info in tracker_dict.items(): + old_cx, old_cy = info['pos'] + if abs(cx - old_cx) < 30 and abs(cy - old_cy) < 30: + matched_id = vid + break + + if matched_id is None: + matched_id = vehicle_id_counter + vehicle_id_counter += 1 + tracker_dict[matched_id] = { + 'pos': (cx, cy), + 'last_cy': cy, + 't1': None, + 't2': None, + 'direction': None, + 'logged': False + } + else: + tracker_dict[matched_id]['pos'] = (cx, cy) + + vehicle = tracker_dict[matched_id] + last_cy = vehicle['last_cy'] + + # Detect downward movement + if not vehicle['t1'] and last_cy < speed_line_y1 <= cy: + vehicle['t1'] = datetime.now() + elif vehicle['t1'] and not vehicle['t2'] and last_cy < speed_line_y2 <= cy: + vehicle['t2'] = datetime.now() + vehicle['direction'] = 'down' + + # Detect upward movement + elif not vehicle['t1'] and last_cy > speed_line_y2 >= cy: + vehicle['t1'] = datetime.now() + elif vehicle['t1'] and not vehicle['t2'] and last_cy > speed_line_y1 >= cy: + vehicle['t2'] = datetime.now() + vehicle['direction'] = 'up' + + vehicle['last_cy'] = cy + + # Speed and database log + if vehicle['t1'] and vehicle['t2'] and not vehicle['logged']: + delta_time = (vehicle['t2'] - vehicle['t1']).total_seconds() + if delta_time > 0: + speed_kmh = (real_world_distance_m / delta_time) * 3.6 + if speed_kmh >= min_speed_kmh: + print(f"ID {matched_id} SPEED: {speed_kmh:.2f} km/h DIRECTION: {vehicle['direction']}") + cursor.execute( + "INSERT INTO vehicle_log (vehicle_id, direction, timestamp, speed) VALUES (%s, %s, %s, %s)", + (matched_id, vehicle['direction'], datetime.now(), round(speed_kmh, 2)) + ) + conn.commit() + else: + print(f"ID {matched_id} IGNORED (too slow): {speed_kmh:.2f} km/h") + vehicle['logged'] = True + + # Label + cv2.putText(frame, f"ID:{matched_id}", (x, y - 5), + cv2.FONT_HERSHEY_SIMPLEX, 0.4, (0, 255, 255), 1) + + if vehicle['t1'] and vehicle['t2']: + delta_time = (vehicle['t2'] - vehicle['t1']).total_seconds() + if delta_time > 0: + speed_kmh = (real_world_distance_m / delta_time) * 3.6 + cv2.putText(frame, f"{speed_kmh:.1f} km/h", (x, y + h + 15), + cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 255, 0), 2) + + if speed_line_y1 <= cy <= speed_line_y2: + vehicle_ids_in_zone.add(matched_id) + + # Store vehicle count in zone + if vehicle_ids_in_zone != last_vehicle_ids_in_zone: + last_vehicle_ids_in_zone = vehicle_ids_in_zone.copy() + count = len(vehicle_ids_in_zone) + cursor.execute("INSERT INTO total_vehicle (count, timestamp) VALUES (%s, %s)", (count, datetime.now())) + conn.commit() + print(f"🚗 Vehicles in zone: {count}") + + # Draw lines + cv2.line(frame, (0, speed_line_y1), (width2, speed_line_y1), (0, 255, 255), 2) + cv2.line(frame, (0, speed_line_y2), (width2, speed_line_y2), (255, 0, 255), 2) + + cv2.imshow("Vehicle Detection", frame) + if cv2.waitKey(1) & 0xFF == 27: + break + +# Cleanup +cap.release() +cursor.close() +conn.close() +cv2.destroyAllWindows() diff --git a/app7.py b/app7.py new file mode 100644 index 0000000..ccf17df --- /dev/null +++ b/app7.py @@ -0,0 +1,174 @@ +import cv2 +import numpy as np +import pymysql +from datetime import datetime + +# DB Connection +conn = pymysql.connect( + host='localhost', + user='root', + password='', + database='db_traffic2' +) +cursor = conn.cursor() + +# RTSP or video +cap = cv2.VideoCapture('rtsp://20.20.20.33:8554/') +ret, frame = cap.read() +if not ret: + print("Failed to read from source.") + exit() + +height2, width2, _ = frame.shape +cv2.setUseOptimized(True) + +fgbg = cv2.createBackgroundSubtractorMOG2() + +vehicle_id_counter = 0 +tracker_dict = {} + +# Line positions & buffer +speed_line_y1 = 265 +speed_line_y2 = 360 +buffer = 10 + +# Real-world distance between lines (meters) +real_world_distance_m = 0.25 +min_speed_kmh = 10 # Threshold + +last_vehicle_ids_in_zone = set() + +while True: + ret, frame = cap.read() + if not ret: + break + + gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) + fgmask = fgbg.apply(gray) + + kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5, 5)) + closing = cv2.morphologyEx(fgmask, cv2.MORPH_CLOSE, kernel) + opening = cv2.morphologyEx(closing, cv2.MORPH_OPEN, kernel) + dilation = cv2.dilate(opening, kernel) + _, bins = cv2.threshold(dilation, 220, 255, cv2.THRESH_BINARY) + + contours, _ = cv2.findContours(bins, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)[-2:] + cv2.drawContours(frame, [cv2.convexHull(c) for c in contours], -1, (0, 255, 0), 2) + + min_area = 200 + max_area = 40000 + vehicle_ids_in_zone = set() + + for cnt in contours: + area = cv2.contourArea(cnt) + if not (min_area < area < max_area): + continue + + M = cv2.moments(cnt) + if M['m00'] == 0: + continue + cx = int(M['m10'] / M['m00']) + cy = int(M['m01'] / M['m00']) + + x, y, w, h = cv2.boundingRect(cnt) + cv2.rectangle(frame, (x, y), (x + w, y + h), (255, 0, 0), 2) + cv2.drawMarker(frame, (cx, cy), (0, 0, 255), cv2.MARKER_CROSS, 10, 1) + + matched_id = None + for vid, info in tracker_dict.items(): + old_cx, old_cy = info['pos'] + if abs(cx - old_cx) < 30 and abs(cy - old_cy) < 30: + matched_id = vid + break + + if matched_id is None: + matched_id = vehicle_id_counter + vehicle_id_counter += 1 + tracker_dict[matched_id] = { + 'pos': (cx, cy), + 'last_cy': cy, + 't1': None, + 't2': None, + 'direction': None, + 'logged': False + } + else: + tracker_dict[matched_id]['pos'] = (cx, cy) + + vehicle = tracker_dict[matched_id] + last_cy = vehicle['last_cy'] + + # Detect downward direction + if not vehicle['t1'] and last_cy < (speed_line_y1 - buffer) <= cy: + vehicle['t1'] = datetime.now() + elif vehicle['t1'] and not vehicle['t2'] and last_cy < (speed_line_y2 - buffer) <= cy: + vehicle['t2'] = datetime.now() + vehicle['direction'] = 'down' + + # Detect upward direction + elif not vehicle['t1'] and last_cy > (speed_line_y2 + buffer) >= cy: + vehicle['t1'] = datetime.now() + elif vehicle['t1'] and not vehicle['t2'] and last_cy > (speed_line_y1 + buffer) >= cy: + vehicle['t2'] = datetime.now() + vehicle['direction'] = 'up' + + vehicle['last_cy'] = cy + + # Visual indicators for debug + if vehicle['t1']: + cv2.circle(frame, (cx, cy), 5, (0, 255, 255), -1) + if vehicle['t2']: + cv2.circle(frame, (cx, cy), 5, (255, 0, 255), -1) + + # Speed and database log + if vehicle['t1'] and vehicle['t2'] and not vehicle['logged']: + delta_time = (vehicle['t2'] - vehicle['t1']).total_seconds() + if delta_time > 0: + speed_kmh = (real_world_distance_m / delta_time) * 3.6 + if speed_kmh >= min_speed_kmh: + print(f"ID {matched_id} SPEED: {speed_kmh:.2f} km/h DIRECTION: {vehicle['direction']}") + cursor.execute( + "INSERT INTO vehicle_log (vehicle_id, direction, timestamp, speed) VALUES (%s, %s, %s, %s)", + (matched_id, vehicle['direction'], datetime.now(), round(speed_kmh, 2)) + ) + conn.commit() + else: + print(f"ID {matched_id} IGNORED (too slow): {speed_kmh:.2f} km/h") + vehicle['logged'] = True + + # Display ID & speed + cv2.putText(frame, f"ID:{matched_id}", (x, y - 5), + cv2.FONT_HERSHEY_SIMPLEX, 0.4, (0, 255, 255), 1) + + if vehicle['t1'] and vehicle['t2']: + delta_time = (vehicle['t2'] - vehicle['t1']).total_seconds() + if delta_time > 0: + speed_kmh = (real_world_distance_m / delta_time) * 3.6 + cv2.putText(frame, f"{speed_kmh:.1f} km/h", (x, y + h + 15), + cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 255, 0), 2) + + # Zone counting + if speed_line_y1 <= cy <= speed_line_y2: + vehicle_ids_in_zone.add(matched_id) + + # Store zone count if changed + if vehicle_ids_in_zone != last_vehicle_ids_in_zone: + last_vehicle_ids_in_zone = vehicle_ids_in_zone.copy() + count = len(vehicle_ids_in_zone) + cursor.execute("INSERT INTO total_vehicle (count, timestamp) VALUES (%s, %s)", (count, datetime.now())) + conn.commit() + print(f"🚗 Vehicles in zone: {count}") + + # Draw detection lines + cv2.line(frame, (0, speed_line_y1), (width2, speed_line_y1), (0, 255, 255), 2) + cv2.line(frame, (0, speed_line_y2), (width2, speed_line_y2), (255, 0, 255), 2) + + cv2.imshow("Vehicle Detection", frame) + if cv2.waitKey(1) & 0xFF == 27: + break + +# Cleanup +cap.release() +cursor.close() +conn.close() +cv2.destroyAllWindows() diff --git a/image.png b/image.png new file mode 100644 index 0000000..67d4460 Binary files /dev/null and b/image.png differ diff --git a/image2.png b/image2.png new file mode 100644 index 0000000..428db64 Binary files /dev/null and b/image2.png differ diff --git a/jalankan.py b/jalankan.py new file mode 100644 index 0000000..46fefb1 --- /dev/null +++ b/jalankan.py @@ -0,0 +1,11 @@ +import subprocess + +# Jalankan app.py +p1 = subprocess.Popen(["python", "this.py"]) + +# Jalankan main.py +p2 = subprocess.Popen(["python", "main1.py"]) + +# Tunggu keduanya selesai (opsional, biasanya biarkan berjalan) +p1.wait() +p2.wait() diff --git a/main1.py b/main1.py new file mode 100644 index 0000000..414676b --- /dev/null +++ b/main1.py @@ -0,0 +1,52 @@ +from flask import Flask, jsonify, render_template +import pymysql + +app = Flask(__name__) + +# Database config +db_config = { + 'host': 'localhost', + 'user': 'root', + 'password': '', + 'database': 'db_traffic2' +} + +@app.route('/') +def index(): + return render_template('index.html') + +@app.route('/get_video') +def get_video_data(): + try: + conn = pymysql.connect(**db_config) + cursor = conn.cursor(pymysql.cursors.DictCursor) + + # Total vehicle log entries + cursor.execute("SELECT COUNT(*) AS total FROM vehicle_log") + total = cursor.fetchone()['total'] + + # Last 10 vehicle log entries + cursor.execute("SELECT * FROM vehicle_log ORDER BY id DESC LIMIT 10") + last_records = cursor.fetchall() + + # Get latest count from total_vehicle table + cursor.execute("SELECT count FROM total_vehicle ORDER BY id DESC LIMIT 1") + latest_vehicle_count = cursor.fetchone() + current_count = latest_vehicle_count['count'] if latest_vehicle_count else 0 + + return jsonify({ + 'total_entries': total, + 'last_10_entries': last_records, + 'vehicles_in_zone': current_count # ⬅️ NEW FIELD + }) + + except Exception as e: + return jsonify({'error': str(e)}), 500 + + finally: + cursor.close() + conn.close() + + +if __name__ == '__main__': + app.run(debug=True, port=5000) diff --git a/pagi.mp4 b/pagi.mp4 new file mode 100755 index 0000000..d5b8fc7 Binary files /dev/null and b/pagi.mp4 differ diff --git a/readme.md b/readme.md new file mode 100644 index 0000000..83bfe9b --- /dev/null +++ b/readme.md @@ -0,0 +1,6 @@ +# Traffic monitoring + +## Traffic monitoring using opencv, monitoring vehicles in real time and save to database +## You can view the data on flask +![This is the monitoring](image.png) +![This is the result](image2.png) \ No newline at end of file diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..2d2c744 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,44 @@ +blinker==1.9.0 +certifi==2025.7.14 +charset-normalizer==3.4.2 +click==8.2.1 +contourpy==1.3.2 +cycler==0.12.1 +deep-sort-realtime==1.3.2 +filelock==3.18.0 +Flask==3.1.1 +fonttools==4.58.5 +fsspec==2025.5.1 +idna==3.10 +itsdangerous==2.2.0 +Jinja2==3.1.6 +kiwisolver==1.4.8 +MarkupSafe==3.0.2 +matplotlib==3.10.3 +mpmath==1.3.0 +networkx==3.4.2 +numpy==1.24.4 +opencv-python==4.12.0.88 +packaging==25.0 +pandas==2.3.1 +pillow==11.3.0 +psutil==7.0.0 +py-cpuinfo==9.0.0 +PyMySQL==1.1.1 +pyparsing==3.2.3 +python-dateutil==2.9.0.post0 +pytz==2025.2 +PyYAML==6.0.2 +requests==2.32.4 +scipy==1.15.3 +six==1.17.0 +sympy==1.14.0 +torch==2.2.2 +torchvision==0.17.2 +tqdm==4.67.1 +typing_extensions==4.14.1 +tzdata==2025.2 +ultralytics==8.3.166 +ultralytics-thop==2.0.14 +urllib3==2.5.0 +Werkzeug==3.1.3 diff --git a/templates/index.html b/templates/index.html new file mode 100644 index 0000000..3d87974 --- /dev/null +++ b/templates/index.html @@ -0,0 +1,114 @@ + + + + + Traffic Monitor + + + +

🚦 Traffic Logger Dashboard

+ +
+
🔢 Total Vehicle Log Entries: Loading...
+
🚗 Vehicles Currently Between Lines: Loading...
+
+ +

📋 Last 10 Vehicle Entries

+ + + + + + + + + + + + + +
IDVehicle IDDirectionTimestampSpeed (km/h)
Loading data...
+ + + + diff --git a/this.py b/this.py new file mode 100644 index 0000000..24b05a5 --- /dev/null +++ b/this.py @@ -0,0 +1,164 @@ +import cv2 +import numpy as np +import pymysql +from datetime import datetime + +# Database connection +conn = pymysql.connect( + host='localhost', + user='root', + password='', + database='db_traffic2' +) +cursor = conn.cursor() + +# RTSP stream or test video +cap = cv2.VideoCapture('pagi.mp4') # Replace with RTSP URL when needed + +# Get original width and height +ret, frame = cap.read() +if not ret: + print("Failed to read from video source.") + exit() + +height2, width2, channels = frame.shape + +# Background subtractor +fgbg = cv2.createBackgroundSubtractorMOG2() + +# Vehicle tracking and speed +vehicle_id_counter = 0 +tracker_dict = {} +speed_line_y1 = 245 +speed_line_y2 = 355 +meters_travel_pixel = 0.2 + +last_vehicle_ids_in_zone = set() + +while True: + ret, frame = cap.read() + if not ret: + break + + gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) + fgmask = fgbg.apply(gray) + + kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5, 5)) + closing = cv2.morphologyEx(fgmask, cv2.MORPH_CLOSE, kernel) + opening = cv2.morphologyEx(closing, cv2.MORPH_OPEN, kernel) + dilation = cv2.dilate(opening, kernel) + _, bins = cv2.threshold(dilation, 220, 255, cv2.THRESH_BINARY) + + contours, _ = cv2.findContours(bins, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)[-2:] + hull = [cv2.convexHull(c) for c in contours] + cv2.drawContours(frame, hull, -1, (0, 255, 0), 2) + + min_area = 400 + max_area = 40000 + + vehicle_ids_in_zone = set() + + for cnt in contours: + area = cv2.contourArea(cnt) + if min_area < area < max_area: + M = cv2.moments(cnt) + if M['m00'] == 0: + continue + cx = int(M['m10'] / M['m00']) + cy = int(M['m01'] / M['m00']) + + if speed_line_y1 <= cy <= speed_line_y2: + vehicle_ids_in_zone.add(matched_id) + + x, y, w, h = cv2.boundingRect(cnt) + cv2.rectangle(frame, (x, y), (x + w, y + h), (255, 0, 0), 2) + cv2.drawMarker(frame, (cx, cy), (0, 0, 255), cv2.MARKER_CROSS, 10, 1) + + matched_id = None + for vid, info in tracker_dict.items(): + old_cx, old_cy = info['pos'] + if abs(cx - old_cx) < 30 and abs(cy - old_cy) < 30: + matched_id = vid + break + + if matched_id is None: + matched_id = vehicle_id_counter + vehicle_id_counter += 1 + tracker_dict[matched_id] = { + 'pos': (cx, cy), + 't1': None, + 't2': None, + 'logged': False, + 'last_cy': cy, + 'direction': None + } + else: + tracker_dict[matched_id]['pos'] = (cx, cy) + + vehicle = tracker_dict[matched_id] + last_cy = vehicle['last_cy'] + vehicle['last_cy'] = cy + + # Downward detection (your original logic) + if not vehicle['t1'] and cy >= speed_line_y1: + vehicle['t1'] = datetime.now() + elif not vehicle['t2'] and cy >= speed_line_y2: + vehicle['t2'] = datetime.now() + vehicle['direction'] = 'down' + + # Upward detection (added logic) + if not vehicle['t1'] and cy <= speed_line_y2: + vehicle['t1'] = datetime.now() + elif not vehicle['t2'] and cy <= speed_line_y1: + vehicle['t2'] = datetime.now() + vehicle['direction'] = 'up' + + # Speed calculation + if vehicle['t1'] and vehicle['t2'] and not vehicle['logged']: + delta_time = (vehicle['t2'] - vehicle['t1']).total_seconds() + if delta_time > 0: + speed_kmh = (meters_travel_pixel / delta_time) * 3.6 + direction = vehicle['direction'] or 'unknown' + print(f"ID {matched_id} SPEED: {speed_kmh:.2f} km/h DIR: {direction}") + + if speed_kmh >= 10: + cursor.execute( + "INSERT INTO vehicle_log (vehicle_id, direction, timestamp, speed) VALUES (%s, %s, %s, %s)", + (matched_id, direction, datetime.now(), round(speed_kmh, 2)) + ) + conn.commit() + vehicle['logged'] = True + + # Show ID + cv2.putText(frame, f"ID:{matched_id}", (x, y - 5), + cv2.FONT_HERSHEY_SIMPLEX, 0.4, (0, 255, 255), 1) + + # Show speed + if vehicle['t1'] and vehicle['t2']: + delta_time = (vehicle['t2'] - vehicle['t1']).total_seconds() + if delta_time > 0: + speed_kmh = (meters_travel_pixel / delta_time) * 3.6 + cv2.putText(frame, f"{speed_kmh:.1f} km/h", (x, y + h + 15), + cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 255, 0), 2) + + + # Store vehicle count in zone + if vehicle_ids_in_zone != last_vehicle_ids_in_zone: + last_vehicle_ids_in_zone = vehicle_ids_in_zone.copy() + count = len(vehicle_ids_in_zone) + cursor.execute("INSERT INTO total_vehicle (count, timestamp) VALUES (%s, %s)", (count, datetime.now())) + conn.commit() + print(f"🚗 Vehicles in zone: {count}") + + # Draw detection lines + cv2.line(frame, (0, speed_line_y1), (width2, speed_line_y1), (0, 255, 255), 2) + cv2.line(frame, (0, speed_line_y2), (width2, speed_line_y2), (255, 0, 255), 2) + + cv2.imshow("Vehicle Detection", frame) + if cv2.waitKey(1) & 0xFF == 27: + break + +cap.release() +cursor.close() +conn.close() +cv2.destroyAllWindows() diff --git a/yolov8n.pt b/yolov8n.pt new file mode 100644 index 0000000..0db4ca4 Binary files /dev/null and b/yolov8n.pt differ