diff --git a/Kepadatan Trafik.ipynb b/Kepadatan Trafik.ipynb new file mode 100644 index 0000000..92ff57e --- /dev/null +++ b/Kepadatan Trafik.ipynb @@ -0,0 +1,460 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "7a0ae93a-02fc-4999-a4b7-f88e44c4db38", + "metadata": {}, + "source": [ + "## Inisialisasi Library" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "e04b411a-7f84-483a-90a3-eb81ccda9495", + "metadata": {}, + "outputs": [], + "source": [ + "import cv2\n", + "import numpy as np\n", + "# import pymysql\n", + "from datetime import datetime" + ] + }, + { + "cell_type": "markdown", + "id": "b4f33820-ca60-4615-9edf-921327bed0f9", + "metadata": {}, + "source": [ + "## Sumber Video (Live atau Lokal Video)" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "2ba1b7b9-f7f8-4a82-adad-41c38464fa7e", + "metadata": {}, + "outputs": [], + "source": [ + "cap = cv2.VideoCapture('pagi.mp4') # 0/1 untuk webcam" + ] + }, + { + "cell_type": "markdown", + "id": "4fe8ad39-92a8-4ccf-8599-841188c6a4bc", + "metadata": {}, + "source": [ + "## mendapatkan tinggi dan lebar video" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "c00caaab-9935-4b32-ac55-94e6abdaa6b5", + "metadata": {}, + "outputs": [], + "source": [ + "# Get original width and height\n", + "ret, frame = cap.read()\n", + "if not ret:\n", + " print(\"Failed to read from video source.\")\n", + " exit()\n", + "\n", + "height2, width2, channels = frame.shape" + ] + }, + { + "cell_type": "markdown", + "id": "6e99de65-f555-4567-b03b-1b6da45b7f7f", + "metadata": {}, + "source": [ + "## Background subtractor , background static" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "5a197d6c-c474-4e4f-9812-dcb03c7cbcab", + "metadata": {}, + "outputs": [], + "source": [ + "fgbg = cv2.createBackgroundSubtractorMOG2()" + ] + }, + { + "cell_type": "markdown", + "id": "1c5725d1-3968-41f4-9fa0-a6ff1ad5400b", + "metadata": {}, + "source": [ + "## Tracking Kenderaan, setup ruas jalan dan pixel travel(untuk menghitung kecepatan kenderaan)" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "2971db44-5b8a-41a8-b6be-9097479c0bfc", + "metadata": {}, + "outputs": [], + "source": [ + "# Vehicle tracking and speed\n", + "vehicle_id_counter = 0\n", + "tracker_dict = {}\n", + "speed_line_y1 = 245\n", + "speed_line_y2 = 355\n", + "meters_travel_pixel = 0.2\n", + "\n", + "last_vehicle_ids_in_zone = set()\n" + ] + }, + { + "cell_type": "markdown", + "id": "6dea54c7-04fc-45cf-b17a-6b8ab58aa367", + "metadata": {}, + "source": [ + "## Proses Video" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "id": "2b15a6b4-c0a7-4fc4-bde7-d3d9e4bf18ee", + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "2025-07-22 08:03:00.245 python[15955:127047] +[IMKClient subclass]: chose IMKClient_Modern\n", + "2025-07-22 08:03:00.246 python[15955:127047] +[IMKInputSession subclass]: chose IMKInputSession_Modern\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "ID 5 SPEED: 9.87 km/h DIR: atas\n", + "ID 4 SPEED: 2.63 km/h DIR: atas\n", + "ID 6 SPEED: 27.53 km/h DIR: atas\n", + "ID 1 SPEED: 0.64 km/h DIR: atas\n", + "ID 7 SPEED: 20.07 km/h DIR: bawah\n", + "ID 8 SPEED: 28.41 km/h DIR: bawah\n", + "ID 10 SPEED: 27.54 km/h DIR: bawah\n", + "ID 11 SPEED: 25.37 km/h DIR: bawah\n", + "ID 9 SPEED: 1.76 km/h DIR: bawah\n", + "ID 12 SPEED: 20.15 km/h DIR: atas\n", + "ID 14 SPEED: 15.12 km/h DIR: atas\n", + "ID 15 SPEED: 4.08 km/h DIR: atas\n", + "ID 16 SPEED: 31.11 km/h DIR: bawah\n", + "ID 21 SPEED: 30.09 km/h DIR: bawah\n", + "ID 22 SPEED: 29.84 km/h DIR: bawah\n", + "ID 23 SPEED: 27.57 km/h DIR: bawah\n", + "ID 24 SPEED: 27.69 km/h DIR: bawah\n", + "ID 25 SPEED: 25.14 km/h DIR: bawah\n", + "ID 26 SPEED: 28.95 km/h DIR: atas\n", + "ID 27 SPEED: 25.72 km/h DIR: atas\n", + "ID 28 SPEED: 7.05 km/h DIR: bawah\n", + "ID 18 SPEED: 0.24 km/h DIR: bawah\n", + "ID 2 SPEED: 0.10 km/h DIR: atas\n", + "ID 31 SPEED: 18.73 km/h DIR: atas\n", + "ID 32 SPEED: 18.70 km/h DIR: atas\n", + "ID 33 SPEED: 4705.88 km/h DIR: atas\n", + "ID 34 SPEED: 18.94 km/h DIR: bawah\n", + "ID 17 SPEED: 0.18 km/h DIR: bawah\n", + "ID 37 SPEED: 2.27 km/h DIR: bawah\n", + "ID 29 SPEED: 0.54 km/h DIR: atas\n", + "ID 42 SPEED: 27.00 km/h DIR: bawah\n", + "ID 40 SPEED: 1.07 km/h DIR: bawah\n", + "ID 45 SPEED: 8.36 km/h DIR: bawah\n", + "ID 51 SPEED: 28.74 km/h DIR: atas\n", + "ID 47 SPEED: 0.16 km/h DIR: bawah\n", + "ID 44 SPEED: 0.05 km/h DIR: bawah\n", + "ID 19 SPEED: 0.04 km/h DIR: bawah\n", + "ID 52 SPEED: 26.06 km/h DIR: bawah\n", + "ID 53 SPEED: 25.74 km/h DIR: bawah\n", + "ID 56 SPEED: 25.56 km/h DIR: atas\n", + "ID 71 SPEED: 7200.00 km/h DIR: atas\n", + "ID 57 SPEED: 25.30 km/h DIR: atas\n", + "ID 58 SPEED: 24.98 km/h DIR: atas\n", + "ID 79 SPEED: 5853.66 km/h DIR: atas\n", + "ID 62 SPEED: 24.75 km/h DIR: atas\n", + "ID 63 SPEED: 22.91 km/h DIR: bawah\n", + "ID 64 SPEED: 22.89 km/h DIR: bawah\n", + "ID 65 SPEED: 22.85 km/h DIR: bawah\n", + "ID 66 SPEED: 22.82 km/h DIR: bawah\n", + "ID 68 SPEED: 22.81 km/h DIR: bawah\n", + "ID 70 SPEED: 22.76 km/h DIR: atas\n", + "ID 72 SPEED: 22.71 km/h DIR: atas\n", + "ID 73 SPEED: 22.66 km/h DIR: atas\n", + "ID 74 SPEED: 22.61 km/h DIR: atas\n", + "ID 75 SPEED: 22.55 km/h DIR: atas\n", + "ID 76 SPEED: 22.52 km/h DIR: atas\n", + "ID 78 SPEED: 22.52 km/h DIR: atas\n", + "ID 77 SPEED: 22.43 km/h DIR: atas\n", + "ID 80 SPEED: 22.58 km/h DIR: atas\n", + "ID 54 SPEED: 8.11 km/h DIR: bawah\n", + "ID 81 SPEED: 11.93 km/h DIR: atas\n", + "ID 59 SPEED: 8.03 km/h DIR: atas\n", + "ID 60 SPEED: 7.99 km/h DIR: atas\n", + "ID 82 SPEED: 8.37 km/h DIR: bawah\n", + "ID 87 SPEED: 12.71 km/h DIR: atas\n", + "ID 88 SPEED: 23.34 km/h DIR: atas\n", + "ID 83 SPEED: 6.17 km/h DIR: atas\n", + "ID 91 SPEED: 23.70 km/h DIR: atas\n", + "ID 95 SPEED: 27.69 km/h DIR: atas\n", + "ID 85 SPEED: 4.19 km/h DIR: bawah\n", + "ID 96 SPEED: 26.43 km/h DIR: atas\n", + "ID 89 SPEED: 1.22 km/h DIR: atas\n", + "ID 99 SPEED: 25.02 km/h DIR: atas\n", + "ID 100 SPEED: 25.04 km/h DIR: atas\n", + "ID 101 SPEED: 25.34 km/h DIR: atas\n", + "ID 86 SPEED: 1.03 km/h DIR: atas\n", + "ID 104 SPEED: 22.98 km/h DIR: atas\n", + "ID 61 SPEED: 0.82 km/h DIR: atas\n", + "ID 92 SPEED: 0.99 km/h DIR: atas\n", + "ID 113 SPEED: 25.80 km/h DIR: atas\n", + "ID 102 SPEED: 3.68 km/h DIR: bawah\n", + "ID 114 SPEED: 14.44 km/h DIR: atas\n", + "ID 30 SPEED: 0.03 km/h DIR: bawah\n", + "ID 116 SPEED: 16.82 km/h DIR: atas\n", + "ID 48 SPEED: 0.03 km/h DIR: bawah\n", + "ID 120 SPEED: 30.18 km/h DIR: bawah\n", + "ID 46 SPEED: 0.03 km/h DIR: bawah\n", + "ID 20 SPEED: 0.02 km/h DIR: bawah\n", + "ID 36 SPEED: 0.02 km/h DIR: bawah\n", + "ID 121 SPEED: 9.60 km/h DIR: atas\n", + "ID 122 SPEED: 5.92 km/h DIR: atas\n", + "ID 43 SPEED: 0.02 km/h DIR: bawah\n", + "ID 124 SPEED: 26.93 km/h DIR: bawah\n", + "ID 125 SPEED: 0.15 km/h DIR: atas\n", + "ID 111 SPEED: 0.02 km/h DIR: atas\n", + "ID 126 SPEED: 0.15 km/h DIR: bawah\n", + "ID 130 SPEED: 17.27 km/h DIR: atas\n", + "ID 13 SPEED: 0.01 km/h DIR: atas\n", + "ID 132 SPEED: 26.91 km/h DIR: atas\n", + "ID 133 SPEED: 27.70 km/h DIR: atas\n", + "ID 110 SPEED: 0.02 km/h DIR: atas\n", + "ID 135 SPEED: 21.77 km/h DIR: atas\n", + "ID 136 SPEED: 29.43 km/h DIR: bawah\n", + "ID 123 SPEED: 0.05 km/h DIR: bawah\n", + "ID 140 SPEED: 4.38 km/h DIR: atas\n", + "ID 129 SPEED: 0.28 km/h DIR: bawah\n", + "ID 107 SPEED: 0.02 km/h DIR: atas\n", + "ID 142 SPEED: 25.03 km/h DIR: atas\n", + "ID 143 SPEED: 25.34 km/h DIR: atas\n", + "ID 145 SPEED: 1.29 km/h DIR: atas\n", + "ID 119 SPEED: 0.03 km/h DIR: bawah\n", + "ID 49 SPEED: 0.01 km/h DIR: bawah\n", + "ID 147 SPEED: 26.32 km/h DIR: bawah\n", + "ID 146 SPEED: 3.69 km/h DIR: bawah\n", + "ID 38 SPEED: 0.01 km/h DIR: bawah\n", + "ID 149 SPEED: 31.98 km/h DIR: bawah\n", + "ID 150 SPEED: 32.99 km/h DIR: bawah\n", + "ID 128 SPEED: 0.06 km/h DIR: bawah\n", + "ID 50 SPEED: 0.01 km/h DIR: bawah\n", + "ID 106 SPEED: 0.02 km/h DIR: atas\n", + "ID 152 SPEED: 21.88 km/h DIR: atas\n", + "ID 153 SPEED: 21.69 km/h DIR: atas\n", + "ID 154 SPEED: 21.67 km/h DIR: atas\n", + "ID 105 SPEED: 0.02 km/h DIR: atas\n", + "ID 118 SPEED: 0.02 km/h DIR: bawah\n", + "ID 156 SPEED: 27.97 km/h DIR: bawah\n", + "ID 109 SPEED: 0.02 km/h DIR: atas\n", + "ID 160 SPEED: 25.02 km/h DIR: bawah\n", + "ID 161 SPEED: 24.71 km/h DIR: atas\n", + "ID 164 SPEED: 28.83 km/h DIR: bawah\n", + "ID 165 SPEED: 27.21 km/h DIR: atas\n", + "ID 162 SPEED: 0.03 km/h DIR: bawah\n", + "ID 157 SPEED: 0.02 km/h DIR: atas\n", + "ID 168 SPEED: 28.21 km/h DIR: atas\n", + "ID 169 SPEED: 27.72 km/h DIR: atas\n", + "ID 159 SPEED: 0.02 km/h DIR: atas\n", + "ID 141 SPEED: 0.01 km/h DIR: atas\n", + "ID 172 SPEED: 1670.53 km/h DIR: atas\n", + "ID 151 SPEED: 0.02 km/h DIR: bawah\n", + "ID 171 SPEED: 15.26 km/h DIR: atas\n", + "ID 112 SPEED: 0.01 km/h DIR: atas\n", + "ID 173 SPEED: 12.57 km/h DIR: bawah\n", + "ID 84 SPEED: 0.01 km/h DIR: atas\n", + "ID 103 SPEED: 0.01 km/h DIR: atas\n", + "ID 175 SPEED: 20.23 km/h DIR: bawah\n", + "ID 176 SPEED: 22.56 km/h DIR: bawah\n", + "ID 177 SPEED: 26.29 km/h DIR: bawah\n", + "ID 181 SPEED: 25.39 km/h DIR: atas\n", + "ID 182 SPEED: 25.07 km/h DIR: atas\n", + "ID 183 SPEED: 28.20 km/h DIR: atas\n", + "ID 167 SPEED: 0.03 km/h DIR: bawah\n", + "ID 108 SPEED: 0.01 km/h DIR: atas\n", + "ID 35 SPEED: 0.01 km/h DIR: bawah\n" + ] + } + ], + "source": [ + "while True:\n", + " ret, frame = cap.read()\n", + " if not ret:\n", + " break\n", + "\n", + " gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)\n", + " fgmask = fgbg.apply(gray)\n", + "\n", + " kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5, 5))\n", + " closing = cv2.morphologyEx(fgmask, cv2.MORPH_CLOSE, kernel)\n", + " opening = cv2.morphologyEx(closing, cv2.MORPH_OPEN, kernel)\n", + " dilation = cv2.dilate(opening, kernel)\n", + " _, bins = cv2.threshold(dilation, 220, 255, cv2.THRESH_BINARY)\n", + "\n", + " contours, _ = cv2.findContours(bins, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)[-2:]\n", + " hull = [cv2.convexHull(c) for c in contours]\n", + " cv2.drawContours(frame, hull, -1, (0, 255, 0), 2)\n", + "\n", + " min_area = 400\n", + " max_area = 40000\n", + "\n", + " vehicle_ids_in_zone = set()\n", + "\n", + " for cnt in contours:\n", + " area = cv2.contourArea(cnt)\n", + " if min_area < area < max_area:\n", + " M = cv2.moments(cnt)\n", + " if M['m00'] == 0:\n", + " continue\n", + " cx = int(M['m10'] / M['m00'])\n", + " cy = int(M['m01'] / M['m00'])\n", + "\n", + " matched_id = None\n", + " for vid, info in tracker_dict.items():\n", + " old_cx, old_cy = info['pos']\n", + " if abs(cx - old_cx) < 30 and abs(cy - old_cy) < 30:\n", + " matched_id = vid\n", + " break\n", + "\n", + " if matched_id is None:\n", + " matched_id = vehicle_id_counter\n", + " vehicle_id_counter += 1\n", + " tracker_dict[matched_id] = {\n", + " 'pos': (cx, cy),\n", + " 't1': None,\n", + " 't2': None,\n", + " 'logged': False,\n", + " 'last_cy': cy,\n", + " 'direction': None\n", + " }\n", + " else:\n", + " tracker_dict[matched_id]['pos'] = (cx, cy)\n", + "\n", + " vehicle = tracker_dict[matched_id]\n", + " last_cy = vehicle['last_cy']\n", + " vehicle['last_cy'] = cy\n", + "\n", + " if speed_line_y1 <= cy <= speed_line_y2:\n", + " vehicle_ids_in_zone.add(matched_id)\n", + "\n", + " x, y, w, h = cv2.boundingRect(cnt)\n", + " cv2.rectangle(frame, (x, y), (x + w, y + h), (255, 0, 0), 2)\n", + " cv2.drawMarker(frame, (cx, cy), (0, 0, 255), cv2.MARKER_CROSS, 10, 1)\n", + "\n", + " # Downward detection\n", + " if not vehicle['t1'] and cy >= speed_line_y1:\n", + " vehicle['t1'] = datetime.now()\n", + " elif not vehicle['t2'] and cy >= speed_line_y2:\n", + " vehicle['t2'] = datetime.now()\n", + " vehicle['direction'] = 'bawah'\n", + "\n", + " # Upward detection\n", + " if not vehicle['t1'] and cy <= speed_line_y2:\n", + " vehicle['t1'] = datetime.now()\n", + " elif not vehicle['t2'] and cy <= speed_line_y1:\n", + " vehicle['t2'] = datetime.now()\n", + " vehicle['direction'] = 'atas'\n", + "\n", + " # Speed calculation\n", + " if vehicle['t1'] and vehicle['t2'] and not vehicle['logged']:\n", + " delta_time = (vehicle['t2'] - vehicle['t1']).total_seconds()\n", + " if delta_time > 0:\n", + " speed_kmh = (meters_travel_pixel / delta_time) * 3.6\n", + " direction = vehicle['direction'] or 'unknown'\n", + " print(f\"ID {matched_id} SPEED: {speed_kmh:.2f} km/h DIR: {direction}\")\n", + " vehicle['logged'] = True\n", + "\n", + " # Show ID\n", + " cv2.putText(frame, f\"ID:{matched_id}\", (x, y - 5),\n", + " cv2.FONT_HERSHEY_SIMPLEX, 0.4, (0, 255, 255), 1)\n", + "\n", + " # Show speed\n", + " if vehicle['t1'] and vehicle['t2']:\n", + " delta_time = (vehicle['t2'] - vehicle['t1']).total_seconds()\n", + " if delta_time > 0:\n", + " speed_kmh = (meters_travel_pixel / delta_time) * 3.6\n", + " cv2.putText(frame, f\"{speed_kmh:.1f} km/h\", (x, y + h + 15),\n", + " cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 255, 0), 2)\n", + "\n", + " # Kepadatan kendaraan per 1km\n", + " kendaraan_dalam_zona = len(vehicle_ids_in_zone)\n", + " panjang_zona_meter = 20 # Panjang zona real di lapangan\n", + " kepadatan_per_meter = kendaraan_dalam_zona / panjang_zona_meter\n", + " kepadatan_per_km = kepadatan_per_meter * 1000\n", + "\n", + " if kepadatan_per_meter <= 0.05:\n", + " status = \"Kepadatan sepi\"\n", + " color = (0, 255, 0)\n", + " elif kepadatan_per_meter <= 0.20:\n", + " status = \"Kepadatan sedang\"\n", + " color = (0, 255, 255)\n", + " else:\n", + " status = \"Kepadatan padat\"\n", + " color = (0, 0, 255)\n", + "\n", + " cv2.putText(frame, f\"{status} | {kepadatan_per_km:.1f} kendaraan/km\", (20, 40),\n", + " cv2.FONT_HERSHEY_SIMPLEX, 0.7, color, 2)\n", + "\n", + " # Draw detection lines\n", + " cv2.line(frame, (0, speed_line_y1), (width2, speed_line_y1), (0, 255, 255), 2)\n", + " cv2.line(frame, (0, speed_line_y2), (width2, speed_line_y2), (255, 0, 255), 2)\n", + "\n", + " cv2.imshow(\"Vehicle Detection\", frame)\n", + " if cv2.waitKey(1) & 0xFF == 27:\n", + " break" + ] + }, + { + "cell_type": "markdown", + "id": "528fec84-623f-43af-9ca9-c9a39c94d58b", + "metadata": {}, + "source": [ + "## Matikan OpenCV" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "id": "a1991228-a38c-4476-b5a4-7414038eda39", + "metadata": {}, + "outputs": [], + "source": [ + "cap.release()\n", + "cv2.destroyAllWindows()" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.12" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/dapp.py b/dapp.py new file mode 100644 index 0000000..5d866e5 --- /dev/null +++ b/dapp.py @@ -0,0 +1,119 @@ +import cv2 +import numpy as np +import math +import time +from collections import deque + +cap = cv2.VideoCapture("pagi.mp4") # Replace with your video file or camera index + +fgbg = cv2.createBackgroundSubtractorMOG2(history=500, varThreshold=100) +kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (3, 3)) + +tracking = {} +counter = 0 +next_vehicle_id = 0 + +# Define diagonal speed lines (you can adjust the points to match your scene) +# Diagonal lines (you can draw these on your video to test) +speed_line_1 = ((100, 500), (800, 250)) +speed_line_2 = ((110, 390), (800, 180)) + +font = cv2.FONT_HERSHEY_SIMPLEX + +while True: + ret, frame = cap.read() + if not ret: + break + + fgmask = fgbg.apply(frame) + fgmask = cv2.morphologyEx(fgmask, cv2.MORPH_OPEN, kernel) + + contours, _ = cv2.findContours(fgmask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) + + centers = [] + for cnt in contours: + if cv2.contourArea(cnt) > 500: + x, y, w, h = cv2.boundingRect(cnt) + cx = x + w // 2 + cy = y + h // 2 + centers.append((cx, cy)) + cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 2) + + updated_tracking = {} + for center in centers: + cx, cy = center + matched = None + for vid, vehicle in tracking.items(): + prev_center = vehicle['center'] + if math.hypot(cx - prev_center[0], cy - prev_center[1]) < 50: + matched = vid + break + + if matched is not None: + vehicle = tracking[matched] + dx = cx - vehicle['center'][0] + dy = cy - vehicle['center'][1] + angle = math.degrees(math.atan2(dy, dx)) + + if -45 <= angle <= 45: + direction = 'kanan' + elif 45 < angle <= 135: + direction = 'bawah' + elif angle > 135 or angle < -135: + direction = 'kiri' + else: + direction = 'atas' + + vehicle['center'] = (cx, cy) + vehicle['trace'].append((cx, cy)) + vehicle['last_seen'] = time.time() + vehicle['direction'] = direction + + # Check if crossed diagonal speed lines + if not vehicle['crossed']: + line1 = speed_line_1 + line2 = speed_line_2 + trace = vehicle['trace'] + if len(trace) >= 2: + for i in range(len(trace) - 1): + if cv2.clipLine(line1, trace[i], trace[i+1])[0] and cv2.clipLine(line2, trace[i], trace[i+1])[0]: + t1 = vehicle['timestamps'][i] + t2 = time.time() + duration = t2 - t1 + distance_m = 2.0 # assume 2 meters between lines + speed = (distance_m / duration) * 3.6 + vehicle['speed'] = round(speed, 2) + vehicle['crossed'] = True + break + + updated_tracking[matched] = vehicle + else: + updated_tracking[next_vehicle_id] = { + 'center': (cx, cy), + 'trace': deque([(cx, cy)], maxlen=32), + 'timestamps': deque([time.time()], maxlen=32), + 'last_seen': time.time(), + 'direction': None, + 'speed': None, + 'crossed': False + } + next_vehicle_id += 1 + + tracking = updated_tracking + + for vid, vehicle in tracking.items(): + cx, cy = vehicle['center'] + if vehicle['speed']: + cv2.putText(frame, f"ID:{vid} {vehicle['direction']} {vehicle['speed']} km/h", (cx, cy), font, 0.5, (0, 255, 255), 2) + else: + cv2.putText(frame, f"ID:{vid} {vehicle['direction']}", (cx, cy), font, 0.5, (255, 255, 0), 2) + + cv2.line(frame, speed_line_1[0], speed_line_1[1], (255, 0, 0), 2) + cv2.line(frame, speed_line_2[0], speed_line_2[1], (0, 0, 255), 2) + + cv2.imshow('Diagonal Vehicle Tracking', frame) + if cv2.waitKey(30) & 0xFF == 27: + break + +cap.release() +cv2.destroyAllWindows() diff --git a/templates/index.html b/templates/index.html index fdc173a..fb5344a 100644 --- a/templates/index.html +++ b/templates/index.html @@ -107,14 +107,25 @@ document.getElementById('total-entries').textContent = data.total_entries; document.getElementById('vehicle-zone').textContent = data.vehicles_in_zone; - if (data.vehicles_in_zone <= 2) { - document.getElementById('kepadatan').textContent = 'Kepadatan sepi'; - } else if (data.vehicles_in_zone <= 5) { - document.getElementById('kepadatan').textContent = 'Kepadatan sedang'; + const N = data.vehicles_in_zone; // Jumlah kendaraan terdeteksi dalam L meter + const L = 20; // Panjang zona deteksi (dalam meter) + const P = N / L; // Kepadatan kendaraan per meter + + const kendaraanPerKm = Math.round(P * 1000); // Estimasi kendaraan dalam 1 km + + let keterangan = ''; + if (P <= 0.1) { + keterangan = 'Kepadatan sepi'; + } else if (P <= 0.20) { + keterangan = 'Kepadatan sedang'; } else { - document.getElementById('kepadatan').textContent = 'Kepadatan tinggi'; + keterangan = 'Kepadatan tinggi'; } + keterangan += ` | Estimasi ${kendaraanPerKm} kendaraan per 1 km`; + + document.getElementById('kepadatan').textContent = keterangan; + // Populate table const tbody = document.getElementById('log-table-body'); tbody.innerHTML = ''; @@ -141,7 +152,7 @@ loadData(); // Refresh every 10 seconds - setInterval(loadData, 5000); + setInterval(loadData, 2500);