{ "cells": [ { "cell_type": "markdown", "id": "37fe6724-f5fe-412a-ab9a-6a1df878c308", "metadata": {}, "source": [ "## Import Library" ] }, { "cell_type": "code", "execution_count": 15, "id": "11b66fe3-8d38-4bf9-b9c5-f8bd3213bd55", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Selesai Import Library\n" ] } ], "source": [ "import cv2 # Import library OpenCV untuk pengolahan citra dan video\n", "import imutils # Import library imutils untuk mempermudah manipulasi citra\n", "import numpy as np # Import library numpy untuk operasi numerik\n", "from ultralytics import YOLO # Import class YOLO dari library ultralytics untuk deteksi objek\n", "from collections import defaultdict # Import class defaultdict dari library collections untuk struktur data default dictionary\n", "\n", "print(\"Selesai Import Library\")" ] }, { "cell_type": "markdown", "id": "243e5a8f-46c2-4fe1-b174-52a46f0a26ee", "metadata": {}, "source": [ "## Deklarasi Variable" ] }, { "cell_type": "code", "execution_count": 16, "id": "bbeb303b-5683-44cc-a924-0f2481d75528", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "selesai deklarasi variable\n" ] } ], "source": [ "color = (0, 255, 0) # Warna hijau untuk penggambaran objek dan garis\n", "color_red = (0, 0, 255) # Warna merah untuk teks dan garis\n", "thickness = 2 # Ketebalan garis untuk penggambaran objek dan garis\n", "\n", "font = cv2.FONT_HERSHEY_SIMPLEX # Jenis font untuk teks\n", "font_scale = 0.5 # Skala font untuk teks\n", "\n", "# Path video yang akan diproses\n", "video_path = \"video.mp4\"\n", "model_path = \"models/yolov8n.pt\"\n", "\n", "# Buka video\n", "cap = cv2.VideoCapture(video_path)\n", "# Inisialisasi model YOLO dengan file weight yang telah dilatih sebelumnya\n", "model = YOLO(model_path)\n", "\n", "# Ukuran frame video\n", "width = 1280\n", "height = 720\n", "\n", "# Inisialisasi objek untuk menyimpan video hasil pemrosesan\n", "fourcc = cv2.VideoWriter_fourcc(*'XVID')\n", "writer = cv2.VideoWriter(\"video.avi\", fourcc, 20.0, (width, height))\n", "\n", "# Id objek kendaraan yang ingin dilacak berdasarkan kelas di file coco-classes.txt\n", "vehicle_ids = [2, 3, 5, 7]\n", "# Dictionary untuk menyimpan sejarah pergerakan setiap kendaraan yang terdeteksi\n", "track_history = defaultdict(lambda: [])\n", "\n", "up = {} # Dictionary untuk kendaraan yang melewati garis atas\n", "down = {} # Dictionary untuk kendaraan yang melewati garis bawah\n", "threshold = 400 # Ambang batas garis pemisah kendaraan\n", "\n", "print(\"selesai deklarasi variable\")" ] }, { "cell_type": "markdown", "id": "00596875-56e1-445a-bd8b-b2b3a73a411a", "metadata": {}, "source": [ "### Fungsi untuk mengambil titik tengah dari bounding box objek " ] }, { "cell_type": "code", "execution_count": 17, "id": "ffcffbd1-ad9b-4908-8930-bea2ba6b6ecb", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Selesai membuat fungsi\n" ] } ], "source": [ "def pega_centro(x, y, w, h):\n", " x1 = int(w / 2)\n", " y1 = int(h / 2)\n", " cx = x + x1\n", " cy = y + y1\n", " return cx, cy\n", "\n", "print(\"Selesai membuat fungsi\")" ] }, { "cell_type": "markdown", "id": "9f2e6c12-a70b-49f2-9083-a9c85b04e842", "metadata": {}, "source": [ "### Background subtraction menggunakan MOG2" ] }, { "cell_type": "code", "execution_count": 18, "id": "4b0f68b8-9216-49e6-892e-bbf2282d73b3", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "selesai\n" ] } ], "source": [ "subtracao = cv2.createBackgroundSubtractorMOG2()\n", "print(\"selesai\")" ] }, { "cell_type": "markdown", "id": "0e9ea925-a617-45d3-b50c-273f4ee0163b", "metadata": {}, "source": [ "## Proses Video " ] }, { "cell_type": "code", "execution_count": 19, "id": "705c59f4-fba5-498d-9e51-d002a0dc3226", "metadata": {}, "outputs": [], "source": [ "# Loop utama untuk membaca setiap frame dari video\n", "while True:\n", " ret, frame = cap.read() # Membaca frame dari video\n", " if ret == False: # Keluar dari loop jika tidak ada frame yang dapat dibaca\n", " break\n", " \n", " try:\n", " frame_color = frame.copy() # Salin frame ke mode warna untuk pengolahan dan penggambaran\n", " frame_gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) # Konversi frame ke citra grayscale\n", " frame_gray = cv2.cvtColor(frame_gray, cv2.COLOR_GRAY2BGR) # Konversi kembali ke citra BGR untuk tampilan grayscale\n", " frame_bw = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) # Konversi ke citra grayscale untuk mode black and white\n", "\n", " # Deteksi objek menggunakan model YOLO\n", " results = model.track(frame_color, persist=True, verbose=False)[0]\n", " bboxes = np.array(results.boxes.data.tolist(), dtype=\"int\") # Koordinat bounding box objek yang terdeteksi\n", "\n", " # Gambar garis pembatas untuk menghitung jumlah kendaraan yang melewati garis\n", " cv2.line(frame_color, (0, threshold), (1280, threshold), color, thickness)\n", " cv2.putText(frame_color, \"Pembatas Jalan\", (620, 445), font, 0.7, color_red, thickness)\n", "\n", " # Loop untuk setiap objek yang terdeteksi\n", " for box in bboxes:\n", " x1, y1, x2, y2, track_id, score, class_id = box # Ambil koordinat dan informasi lainnya\n", " cx = int((x1 + x2) / 2) # Hitung koordinat x pusat objek\n", " cy = int((y1 + y2) / 2) # Hitung koordinat y pusat objek\n", " if class_id in vehicle_ids: # Periksa apakah objek merupakan kendaraan yang ingin dilacak\n", " class_name = results.names[int(class_id)].upper() # Dapatkan nama kelas objek\n", "\n", " track = track_history[track_id] # Ambil sejarah pergerakan objek berdasarkan ID\n", " track.append((cx, cy)) # Tambahkan koordinat pusat objek ke dalam sejarah pergerakan\n", " if len(track) > 20: # Batasi panjang sejarah pergerakan agar tidak terlalu panjang\n", " track.pop(0) # Hapus elemen pertama jika sejarah sudah melebihi batas\n", "\n", " points = np.hstack(track).astype(\"int32\").reshape(-1, 1, 2) # Konversi sejarah pergerakan ke format yang sesuai untuk penggambaran\n", " cv2.polylines(frame_color, [points], isClosed=False, color=color, thickness=thickness) # Gambar garis yang merepresentasikan sejarah pergerakan\n", " cv2.rectangle(frame_color, (x1, y1), (x2, y2), color, thickness) # Gambar bounding box objek\n", " text = \"ID: {} {}\".format(track_id, class_name) # Buat teks ID objek dan nama kelasnya\n", " cv2.putText(frame_color, text, (x1, y1 - 5), font, font_scale, color, thickness) # Tampilkan teks di atas objek\n", "\n", " if cy > threshold - 5 and cy < threshold + 5 and cx < 670: # Periksa apakah objek melewati garis atas\n", " down[track_id] = x1, y1, x2, y2 # Simpan informasi objek yang melewati garis atas\n", "\n", " if cy > threshold - 5 and cy < threshold + 5 and cx > 670: # Periksa apakah objek melewati garis bawah\n", " up[track_id] = x1, y1, x2, y2 # Simpan informasi objek yang melewati garis bawah\n", "\n", " up_text = \"Kanan:{}\".format(len(list(up.keys()))) # Buat teks jumlah kendaraan yang melewati garis atas\n", " down_text = \"Kiri:{}\".format(len(list(down.keys()))) # Buat teks jumlah kendaraan yang melewati garis bawah\n", "\n", " cv2.putText(frame_color, up_text, (1150, threshold - 5), font, 0.8, color_red, thickness) # Tampilkan teks jumlah kendaraan yang melewati garis atas\n", " cv2.putText(frame_color, down_text, (0, threshold - 5), font, 0.8, color_red, thickness) # Tampilkan teks jumlah kendaraan yang melewati garis bawah\n", "\n", " # Background subtraction dan deteksi kontur\n", " grey = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) # Konversi frame ke citra grayscale\n", " blur = cv2.GaussianBlur(grey, (3, 3), 5) # Reduksi noise menggunakan Gaussian Blur\n", " img_sub = subtracao.apply(blur) # Background subtraction\n", " dilat = cv2.dilate(img_sub, np.ones((5, 5))) # Dilasi untuk meningkatkan ketebalan objek\n", " kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5, 5)) # Kernel untuk operasi morfologi\n", " dilatada = cv2.morphologyEx(dilat, cv2.MORPH_CLOSE, kernel) # Operasi closing untuk mengisi lubang kecil pada objek\n", " dilatada = cv2.morphologyEx(dilatada, cv2.MORPH_CLOSE, kernel) # Operasi closing tambahan\n", " contorno, h = cv2.findContours(dilatada, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) # Deteksi kontur objek\n", "\n", " writer.write(frame_color) # Menyimpan frame hasil pemrosesan\n", " # Menampilkan gambar\n", " cv2.imshow(\"Warna\", frame_color) # Tampilkan mode warna\n", " cv2.imshow(\"Grayscale\", frame_gray) # Tampilkan mode grayscale\n", " cv2.imshow(\"Detectar\", dilatada) # Tampilkan mode Detectar dilatada\n", " if cv2.waitKey(10) & 0xFF == ord(\"q\"): # Keluar saat tombol q ditekan\n", " break\n", "\n", " except Exception as e:\n", " print(\"Terjadi kesalahan:\", str(e)) # Tangkap dan tampilkan kesalahan yang terjadi\n", " continue # Lanjutkan ke iterasi berikutnya\n" ] }, { "cell_type": "code", "execution_count": null, "id": "08ead243-3140-4f0f-a54b-9c93db2ae6df", "metadata": {}, "outputs": [], "source": [ " \n" ] }, { "cell_type": "code", "execution_count": 20, "id": "15c70b25-1b92-43d8-9167-ebb88b2a8df7", "metadata": {}, "outputs": [], "source": [ "cap.release() # Bebaskan sumber daya setelah selesai pemrosesan video\n", "writer.release() # Tutup objek writer\n", "cv2.destroyAllWindows() # Tutup semua jendela yang dibuka oleh OpenCV" ] } ], "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.10" } }, "nbformat": 4, "nbformat_minor": 5 }