Dokumentasi ini mencakup dua alat bantu (utility scripts) untuk memastikan kualitas data dan distribusi dataset yang seimbang sebelum memasuki tahap training model.
label_validator.py)import os
# --- KONFIGURASI ---
# Ganti dengan path ke folder yang berisi semua file .txt anotasi Anda
# Contoh: 'C:/Users/Farhan/Documents/Projects/Tesis/dataset/D-Fire/train/labels'
labels_dir = 'C:/Users/Farhan/Documents/Projects/Tesis/dataset/D-Fire/test/labels'
#labels_dir = 'C:/Users/Farhan/Documents/Projects/Tesis/dataset/D-Fire/train/labels'
# ---
bad_files = []
print(f"Memindai direktori: {labels_dir}")
# Loop melalui setiap file dalam direktori label
for filename in os.listdir(labels_dir):
if filename.endswith('.txt'):
filepath = os.path.join(labels_dir, filename)
with open(filepath, 'r') as f:
lines = f.readlines()
for line_num, line in enumerate(lines):
parts = line.strip().split()
# 0:class, 1:x_center, 2:y_center, 3:width, 4:height
coords = [float(p) for p in parts[1:]]
# Cek jika ada koordinat di luar rentang [0.0, 1.0]
if any(coord < 0.0 or coord > 1.0 for coord in coords):
print(f"--> ERROR: File '{filename}' baris {line_num + 1} korup: {line.strip()}")
if filename not in bad_files:
bad_files.append(filename)
print("\n--- Pindaian Selesai ---")
if bad_files:
print(f"Ditemukan {len(bad_files)} file anotasi yang berpotensi korup.")
print("Saran: Hapus file .txt ini beserta file gambar yang sesuai, atau perbaiki secara manual.")
else:
print("Selamat! Tidak ditemukan anotasi korup pada direktori ini.")
Skrip ini berfungsi sebagai filter kualitas untuk mendeteksi file anotasi .txt yang korup atau memiliki nilai koordinat di luar batas standar YOLO.
Dalam format YOLO, setiap baris label berisi: class x_center y_center width height. Semua nilai koordinat (x, y, w, h) wajib berada dalam rentang . Jika terdapat nilai di luar rentang tersebut (misal: -0.05 atau 1.12), proses training bisa mengalami error atau menghasilkan akurasi yang tidak valid.
.txt di direktori yang ditentukan.if any(coord < 0.0 or coord > 1.0).dataset_splitter.py)import os
import shutil
import random
# --- 1. KONFIGURASI (UBAH BAGIAN INI) ---
# Ganti dengan path ke folder D-Fire Anda
base_dir = 'C:/Users/Farhan/Documents/Projects/Tesis/dataset/D-Fire'
# Nama folder sumber tempat data Anda sekarang berada
source_train_dir = os.path.join(base_dir, 'train')
source_test_dir = os.path.join(base_dir, 'test')
# Nama folder output baru yang akan dibuat
output_dir = os.path.join(base_dir, 'dataset_split_70_10_20')
# Rasio pembagian yang diinginkan
ratios = {'train': 0.7, 'valid': 0.1, 'test': 0.2}
# ---------------------------------------------
# --- 2. FUNGSI PEMBANTU ---
def copy_files(file_list, source_folder, dest_folder):
"""Menyalin file gambar dan label yang sesuai."""
img_dest_path = os.path.join(dest_folder, 'images')
lbl_dest_path = os.path.join(dest_folder, 'labels')
source_img_dir = os.path.join(source_folder, 'images')
source_lbl_dir = os.path.join(source_folder, 'labels')
for filename in file_list:
base_name = os.path.splitext(filename)[0]
label_filename = base_name + '.txt'
# Path sumber
src_img = os.path.join(source_img_dir, filename)
src_lbl = os.path.join(source_lbl_dir, label_filename)
# Salin file jika ada
if os.path.exists(src_img):
shutil.copy(src_img, img_dest_path)
if os.path.exists(src_lbl):
shutil.copy(src_lbl, lbl_dest_path)
# --- 3. PROSES UTAMA ---
print("Memulai proses pembagian ulang dataset...")
# A. Mengumpulkan semua file dari folder sumber
all_files = []
source_folders_info = {
'train': source_train_dir,
'test': source_test_dir
}
print("Mengumpulkan file dari folder sumber...")
for folder_name, folder_path in source_folders_info.items():
images_path = os.path.join(folder_path, 'images')
if os.path.exists(images_path):
files = os.listdir(images_path)
all_files.extend([(f, folder_name) for f in files]) # Simpan nama file dan asalnya
else:
print(f"Peringatan: Folder {images_path} tidak ditemukan.")
if not all_files:
print("Error: Tidak ada file yang ditemukan. Pastikan path sumber sudah benar.")
exit()
print(f"Total file yang terkumpul: {len(all_files)}.")
# B. Mengacak semua file
random.shuffle(all_files)
print("Semua file telah diacak.")
# C. Menyiapkan folder output baru yang bersih
if os.path.exists(output_dir):
print(f"Menghapus folder output lama: {output_dir}")
shutil.rmtree(output_dir)
print("Membuat struktur folder output baru...")
for split_name in ratios.keys():
os.makedirs(os.path.join(output_dir, split_name, 'images'))
os.makedirs(os.path.join(output_dir, split_name, 'labels'))
# D. Menghitung jumlah file untuk setiap set
total_count = len(all_files)
train_count = int(total_count * ratios['train'])
valid_count = int(total_count * ratios['valid'])
# test_count dihitung dari sisa untuk memastikan semua file terdistribusi
test_count = total_count - train_count - valid_count
# E. Membagi dan menyalin file
print(f"Menyalin {train_count} file ke folder train...")
for filename, origin_folder in all_files[:train_count]:
copy_files([filename], source_folders_info[origin_folder], os.path.join(output_dir, 'train'))
print(f"Menyalin {valid_count} file ke folder valid...")
for filename, origin_folder in all_files[train_count : train_count + valid_count]:
copy_files([filename], source_folders_info[origin_folder], os.path.join(output_dir, 'valid'))
print(f"Menyalin {test_count} file ke folder test...")
for filename, origin_folder in all_files[train_count + valid_count :]:
copy_files([filename], source_folders_info[origin_folder], os.path.join(output_dir, 'test'))
# F. Verifikasi
print("\n--- PROSES SELESAI ---")
print("Verifikasi jumlah file di setiap folder baru:")
final_train_count = len(os.listdir(os.path.join(output_dir, 'train', 'images')))
final_valid_count = len(os.listdir(os.path.join(output_dir, 'valid', 'images')))
final_test_count = len(os.listdir(os.path.join(output_dir, 'test', 'images')))
print(f"Folder train baru: {final_train_count} gambar")
print(f"Folder valid baru: {final_valid_count} gambar")
print(f"Folder test baru : {final_test_count} gambar")
print(f"Total terdistribusi: {final_train_count + final_valid_count + final_test_count} gambar")
print(f"\nStruktur folder baru telah dibuat di: {output_dir}")
Skrip ini digunakan untuk mendistribusikan ulang file gambar dan label ke dalam folder latihan, validasi, dan pengujian dengan rasio yang bisa dikustomisasi.
Dalam penelitian tesis ini, rasio yang digunakan adalah:
images dan labels secara otomatis di bawah direktori dataset_split_70_10_20.label_validator.py pada dataset sumber (D-Fire) untuk memastikan tidak ada data korup.dataset_splitter.py untuk membagi data.dataset_split_70_10_20) sebagai referensi path di dalam file dfire.yaml sebelum memulai training.random.seed (implisit) memastikan bahwa distribusi kelas api dan asap tersebar merata di ketiga folder hasil split.