288 lines
11 KiB
Plaintext
288 lines
11 KiB
Plaintext
{
|
|
"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
|
|
}
|