added jupyter notebook and improve output

This commit is contained in:
kicap
2025-07-23 18:04:28 +08:00
parent 7d2550c3de
commit e438f98cc3
3 changed files with 596 additions and 6 deletions

460
Kepadatan Trafik.ipynb Normal file
View File

@ -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
}