# -*- coding: utf-8 -*- """ Aplikasi Gradio untuk Analisis Komparatif Deteksi Helm Keselamatan ================================================================== Deskripsi: Aplikasi ini memungkinkan pengguna untuk mengunggah video dari lingkungan konstruksi dan membandingkan kinerja dua model AI (YOLOv5m dan YOLOv8m) dalam mendeteksi helm keselamatan secara real-time. Aplikasi ini dirancang untuk menjadi alat evaluasi yang praktis dan mudah digunakan. Fitur Utama: - Perbandingan langsung antara model Generalis (YOLOv5) dan Spesialis (YOLOv8). - Antarmuka pengguna (GUI) yang interaktif dan mudah dipahami. - Pemrosesan video dengan batasan durasi dan resolusi untuk stabilitas. - Menampilkan video hasil dengan anotasi deteksi (bounding box). - Memberikan ringkasan hasil analisis kualitatif dan kuantitatif. - Menyediakan dokumentasi, cara penggunaan, dan kredit yang jelas. Pengembang: Faisal Fahmi Yuliawan Berdasarkan Analisis pada Artikel Ilmiah. """ # --- 1. IMPORT LIBRARY --- import gradio as gr from ultralytics import YOLO import cv2 import numpy as np import os import tempfile import time import logging # --- 2. SETUP & KONFIGURASI AWAL --- # Konfigurasi logging untuk memantau proses logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s') # --- 3. PEMUATAN MODEL AI --- # Memuat kedua model saat aplikasi dimulai untuk respons yang lebih cepat. # Ini menggunakan memori lebih, tetapi meningkatkan pengalaman pengguna. try: logging.info("Memulai pemuatan model AI...") # Model 1: Spesialis (Fokus pada Helm) model_spesialis = YOLO('keremberke/yolov8m-hard-hat-detection') model_spesialis.overrides['conf'] = 0.25 model_spesialis.overrides['iou'] = 0.45 logging.info("✅ Model Spesialis (YOLOv8m-HH) berhasil dimuat.") # Model 2: Generalis (Mendeteksi banyak objek konstruksi) model_generalis = YOLO('keremberke/yolov5m-construction-safety') model_generalis.overrides['conf'] = 0.25 model_generalis.overrides['iou'] = 0.45 logging.info("✅ Model Generalis (YOLOv5m-CS) berhasil dimuat.") # Membuat dictionary untuk kemudahan akses model models = { "YOLOv8m (Spesialis Helm)": model_spesialis, "YOLOv5m (Generalis Konstruksi)": model_generalis } logging.info("Semua model siap digunakan.") except Exception as e: logging.error(f"Gagal memuat salah satu model AI: {e}") # Jika model gagal dimuat, aplikasi tidak dapat berjalan. # Gradio akan menangani error ini dan menampilkannya di UI. raise RuntimeError(f"Tidak dapat memuat model AI. Aplikasi tidak dapat dijalankan. Error: {e}") # --- 4. FUNGSI UTAMA PEMROSESAN VIDEO --- def process_video_and_analyze(video_path, selected_model_name, progress=gr.Progress(track_tqdm=True)): """ Fungsi utama untuk memproses video, melakukan deteksi objek, dan mengembalikan video hasil beserta analisisnya. """ if video_path is None: return None, "Status: Silakan unggah video terlebih dahulu.", "" try: logging.info(f"Memulai pemrosesan video: {video_path} menggunakan model: {selected_model_name}") start_time = time.time() # Pilih model berdasarkan input dari UI model = models[selected_model_name] # Buka file video cap = cv2.VideoCapture(video_path) if not cap.isOpened(): logging.error(f"Gagal membuka file video: {video_path}") return None, "Error: Gagal membuka file video. Format mungkin tidak didukung.", "" # Dapatkan properti video fps = cap.get(cv2.CAP_PROP_FPS) or 30 total_frames = int(cap.get(cv2.CAP_PROP_FRAME_COUNT)) width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)) height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT)) # Batasi resolusi untuk performa yang lebih baik target_width = 640 target_height = int(height * (target_width / width)) if width > 0 else 480 # Konfigurasi video output # Menggunakan tempfile untuk file output sementara temp_output_path = tempfile.NamedTemporaryFile(suffix=".mp4", delete=False).name fourcc = cv2.VideoWriter_fourcc(*"mp4v") out = cv2.VideoWriter(temp_output_path, fourcc, fps, (target_width, target_height)) # Variabel untuk analisis detection_count = 0 helm_detected_count = 0 progress(0, desc="Memulai Pemrosesan...") for frame_idx in range(total_frames): ret, frame = cap.read() if not ret: break # Update progress bar progress(frame_idx / total_frames, desc=f"Memproses Frame {frame_idx+1}/{total_frames}") # Resize frame frame_resized = cv2.resize(frame, (target_width, target_height)) # Lakukan prediksi (inferensi) results = model.predict(frame_resized, verbose=False) # Render hasil deteksi ke frame annotated_frame = results[0].plot() # Hitung deteksi detection_count += len(results[0].boxes) # Hitung deteksi helm secara spesifik if selected_model_name == "YOLOv8m (Spesialis Helm)": for box in results[0].boxes: class_id = int(box.cls) # Kelas '0' biasanya 'Hardhat' di model ini if model.names[class_id].lower() in ['hardhat', 'helmet']: helm_detected_count += 1 elif selected_model_name == "YOLOv5m (Generalis Konstruksi)": for box in results[0].boxes: class_id = int(box.cls) if model.names[class_id].lower() == 'helmet': helm_detected_count += 1 out.write(annotated_frame) end_time = time.time() processing_time = end_time - start_time # Tutup file video cap.release() out.release() logging.info(f"Video berhasil diproses dalam {processing_time:.2f} detik.") # Siapkan teks analisis analysis_text = f""" ### Analisis Kinerja Model: {selected_model_name} - **Waktu Proses Total:** {processing_time:.2f} detik - **Total Frame Diproses:** {total_frames} - **Jumlah Deteksi Keseluruhan:** {detection_count} objek - **Jumlah Deteksi Helm:** {helm_detected_count} objek **Catatan:** - **Model Spesialis (YOLOv8m):** Diharapkan memiliki akurasi deteksi helm yang tinggi, namun hanya mendeteksi kelas terkait helm ('Hardhat', 'NO-Hardhat'). - **Model Generalis (YOLOv5m):** Mampu mendeteksi berbagai objek (11 kelas termasuk 'person', 'vest'), namun akurasi untuk 'helmet' mungkin lebih rendah karena fokusnya terbagi. """ return temp_output_path, f"Status: Video berhasil diproses! ({processing_time:.2f} detik)", analysis_text except Exception as e: logging.error(f"Terjadi error saat memproses video: {e}", exc_info=True) return None, f"Error: Terjadi kesalahan internal - {e}", "" # --- 5. PEMBUATAN ANTARMUKA PENGGUNA (GRADIO UI) --- with gr.Blocks(theme=gr.themes.Soft(primary_hue="blue", secondary_hue="sky")) as iface: # --- Bagian Judul dan Deskripsi --- gr.Markdown( """ # đŸ›Ąī¸ Analisis Komparatif Deteksi Helm Keselamatan Selamat datang di prototipe aplikasi untuk analisis perbandingan model AI dalam mendeteksi helm keselamatan. Aplikasi ini memungkinkan Anda untuk melihat perbedaan kinerja antara model AI yang **spesialis** (hanya untuk helm) dan model AI yang **generalis** (untuk berbagai objek konstruksi). """ ) with gr.Row(): with gr.Column(scale=1): # --- Bagian Input Pengguna --- gr.Markdown("### **Langkah 1: Konfigurasi & Unggah**") selected_model_ui = gr.Radio( choices=list(models.keys()), label="Pilih Model AI untuk Perbandingan", value="YOLOv8m (Spesialis Helm)", info="Pilih algoritma yang ingin Anda gunakan untuk mendeteksi objek." ) video_input = gr.Video( label="Unggah Video Anda", info="Format video yang direkomendasikan adalah .mp4. Durasi maksimal ~30 detik." ) detect_btn = gr.Button("🚀 Mulai Deteksi", variant="primary") gr.Markdown("---") gr.Markdown("### **Cara Penggunaan**") gr.Markdown( """ 1. **Pilih Model AI** yang ingin Anda uji dari opsi di atas. 2. **Unggah file video** dari perangkat Anda atau **pilih contoh** di bawah. 3. Klik tombol **"Mulai Deteksi"** dan tunggu proses selesai. 4. Lihat **video hasil** dan **analisis kinerja** di sebelah kanan. 5. Ulangi dengan model lain untuk melihat perbandingannya. """ ) with gr.Column(scale=1): # --- Bagian Output Hasil --- gr.Markdown("### **Langkah 2: Lihat Hasil Deteksi**") video_output = gr.Video(label="Video Hasil Deteksi") status_text = gr.Textbox(label="Status Proses", interactive=False) gr.Markdown("---") gr.Markdown("### **Ringkasan Analisis**") analysis_output = gr.Markdown(label="Analisis Kinerja") # --- Bagian Contoh Video --- gr.Examples( examples=[ [os.path.join(os.path.dirname(__file__), "video_contoh_1.mp4"), "YOLOv8m (Spesialis Helm)"], [os.path.join(os.path.dirname(__file__), "video_contoh_2.mp4"), "YOLOv5m (Generalis Konstruksi)"] ], inputs=[video_input, selected_model_ui], outputs=[video_output, status_text, analysis_output], fn=process_video_and_analyze, cache_examples=True, label="Contoh Video (Klik untuk mencoba)" ) # --- Bagian Informasi dan Kredit --- with gr.Accordion("â„šī¸ Informasi, Kredit, dan Potensi Pengembangan", open=False): gr.Markdown( """ ### **Identitas Prototipe** - **Pengembang:** Faisal Fahmi Yuliawan (sebagai bagian dari studi ilmiah). - **Tujuan:** Menyediakan alat bantu visual untuk membandingkan kinerja model AI dalam konteks keselamatan kerja (K3), khususnya deteksi helm. - **Relevansi:** Masalah kepatuhan penggunaan APD (Alat Pelindung Diri) seperti helm adalah kasus nyata dan krusial di industri konstruksi untuk mencegah kecelakaan fatal. ### **Kredit Pihak Ketiga** - **Model AI:** - `keremberke/yolov8m-hard-hat-detection` (Model Spesialis) dari Hugging Face. - `keremberke/yolov5m-construction-safety` (Model Generalis) dari Hugging Face. - **Teknologi:** - **Ultralytics YOLO:** Framework utama untuk model AI. - **Gradio:** Framework untuk membangun antarmuka web interaktif ini. - **OpenCV & FFmpeg:** Untuk pemrosesan dan manipulasi video. ### **Potensi Pengembangan & Komersialisasi** - **Skalabilitas:** Arsitektur aplikasi ini dapat dengan mudah diperluas untuk mencakup lebih banyak model AI atau jenis APD lain (misalnya, rompi, sepatu bot, sarung tangan). - **Integrasi:** Dapat diintegrasikan dengan sistem CCTV di lokasi konstruksi untuk pemantauan otomatis dan sistem peringatan *real-time*. - **Potensi Bisnis:** Memiliki potensi komersial sebagai produk SaaS (*Software as a Service*) untuk perusahaan konstruksi yang ingin meningkatkan standar K3 dan melakukan audit kepatuhan secara digital. """ ) # --- Hubungkan Aksi Tombol ke Fungsi --- detect_btn.click( fn=process_video_and_analyze, inputs=[video_input, selected_model_ui], outputs=[video_output, status_text, analysis_output] ) # --- 6. LUNCURKAN APLIKASI --- if __name__ == "__main__": # Untuk menjalankan, simpan kode ini sebagai file .py (misal: app.py) # Buat 2 file video contoh: video_contoh_1.mp4 dan video_contoh_2.mp4 di folder yang sama. # Jalankan dari terminal dengan: python app.py iface.launch(debug=True, share=True)