TakagiTaka's picture
Update app.py
a37d3d7 verified
raw
history blame
12.5 kB
# -*- 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)