{ "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 }