#!/usr/bin/env python3 """ Configuration file for YOLOv8 French ID Card Detection """ import os from pathlib import Path # Base directories BASE_DIR = Path(__file__).parent DATA_DIR = BASE_DIR / "data" LOGS_DIR = BASE_DIR / "logs" # Data configuration DATA_YAML_PATH = DATA_DIR / "data.yaml" # Logging configuration TRAINING_LOG_PATH = LOGS_DIR / "training.log" INFERENCE_LOG_PATH = LOGS_DIR / "inference.log" EVAL_LOG_PATH = LOGS_DIR / "eval.log" # Results directories (sử dụng runs từ YOLO) INFERENCE_RESULTS_DIR = Path("runs/detect") EVALUATION_RESULTS_DIR = Path("runs/val") VISUALIZATION_RESULTS_DIR = Path("runs/detect") # Default configurations DEFAULT_TRAINING_CONFIG = { 'epochs': 100, 'batch': 16, # Sửa từ batch_size thành batch 'imgsz': 640, 'patience': 50, 'save_period': 10, 'device': 'auto', 'project': 'runs/train', 'exist_ok': True, 'pretrained': True, 'optimizer': 'auto', 'verbose': False, # Giảm verbose 'seed': 42, 'deterministic': True, 'single_cls': True, 'rect': False, 'cos_lr': True, 'close_mosaic': 10, 'resume': False, 'amp': True, 'fraction': 1.0, 'cache': False, 'lr0': 0.01, 'lrf': 0.01, 'momentum': 0.937, 'weight_decay': 0.0005, 'warmup_epochs': 3.0, 'warmup_momentum': 0.8, 'warmup_bias_lr': 0.1, 'box': 7.5, 'cls': 0.5, 'dfl': 1.5, 'pose': 12.0, 'kobj': 2.0, 'label_smoothing': 0.0, 'nbs': 64, 'overlap_mask': False, # Tắt mask để tránh tải YOLOv11 'mask_ratio': 4, 'dropout': 0.0, 'val': True, 'plots': True, 'save': True, 'save_json': False, 'save_hybrid': False, 'conf': 0.001, 'iou': 0.6, 'max_det': 300, 'half': True, 'dnn': False, 'plots': True, 'source': None, 'show': False, 'save_txt': False, 'save_conf': False, 'save_crop': False, 'show_labels': True, 'show_conf': True, 'vid_stride': 1, 'line_thickness': 3, 'visualize': False, 'augment': True, # Bật augmentation giống Roboflow 'hsv_s': 0.61, # Saturation augmentation ~61% (Roboflow: Between -61% and +61%) 'hsv_h': 0.015, # Hue augmentation 'hsv_v': 0.4, # Value augmentation 'degrees': 0.0, # Không xoay ảnh 'translate': 0.1, # Dịch chuyển nhẹ 'scale': 0.5, # Scale augmentation 'shear': 0.0, # Không shear 'perspective': 0.0, # Không perspective 'flipud': 0.0, # Không flip vertical 'fliplr': 0.5, # Flip horizontal 50% 'mosaic': 1.0, # Bật mosaic augmentation 'mixup': 0.0, # Không dùng mixup 'copy_paste': 0.0, # Không copy paste 'erasing': 0.08, 'agnostic_nms': False, 'classes': None, 'retina_masks': False, 'boxes': True, 'format': 'torchscript', 'keras': False, 'optimize': False, 'int8': False, 'dynamic': False, 'simplify': False, 'opset': 17, 'workspace': 4, 'nms': False, } DEFAULT_INFERENCE_CONFIG = { 'conf_threshold': 0.25, 'iou_threshold': 0.45, 'max_det': 300, 'line_thickness': 3, 'show_labels': True, 'show_conf': True, } def create_directories(): """Create all necessary directories""" directories = [ LOGS_DIR, ] for directory in directories: directory.mkdir(parents=True, exist_ok=True) print("Directories created successfully") def get_best_model_path(model_size: str = 'n') -> str: """Get path to best trained model from runs/train""" runs_dir = Path('runs/train') if not runs_dir.exists(): return None training_runs = list(runs_dir.glob(f'yolov8_{model_size}_french_id_card')) if not training_runs: return None latest_run = max(training_runs, key=lambda x: x.stat().st_mtime) best_model_path = latest_run / 'weights' / 'best.pt' return str(best_model_path) if best_model_path.exists() else None def get_exported_model_path(model_size: str = 'n', format: str = 'onnx') -> str: """Get path to exported model""" return str(Path("runs/export") / f"yolov8_{model_size}_french_id_card.{format}") def get_latest_training_run(): """Get path to latest training run""" runs_dir = Path('runs/train') if not runs_dir.exists(): return None training_runs = list(runs_dir.glob('yolov8_*_french_id_card')) if not training_runs: return None return max(training_runs, key=lambda x: x.stat().st_mtime) if __name__ == '__main__': create_directories()