# YOLO Annotation Utility Tool YOLO 형식의 어노테이션 파일을 자유롭게 조작할 수 있는 유틸리티 스크립트입니다. ## 주요 기능 - **대화형 모드** (interactive): 터미널에서 대화형으로 편집 (추천!) - **클래스 제거** (remove): 특정 클래스 삭제 (ID 또는 이름으로 지정 가능) - **클래스 통합** (merge): 여러 클래스를 하나로 병합 (ID 또는 이름으로 지정 가능) - **클래스 이름 변경** (rename): 클래스 이름 수정 (ID 또는 이름으로 지정 가능) - **클래스 ID 재할당** (reindex): ID를 순차적으로 재정렬 - **정보 확인** (info): 어노테이션 파일 정보 출력 (클래스별 개수 및 합계 표시) ## 설치 PyYAML 라이브러리가 필요합니다: ```bash pip install pyyaml ``` ## YOLO 데이터셋 구조 이 도구는 다음과 같은 YOLO 데이터셋 구조를 기준으로 동작합니다: ``` dataset/ ├── data.yaml # 클래스 정의 파일 ├── images/ │ ├── train/ │ │ ├── image1.jpg │ │ └── image2.jpg │ └── val/ │ ├── image3.jpg │ └── image4.jpg └── labels/ ├── train/ │ ├── image1.txt │ └── image2.txt └── val/ ├── image3.txt └── image4.txt ``` **data.yaml 예시:** ```yaml names: 0: person 1: car 2: truck 3: bus train: images/train val: images/val ``` **label 파일(.txt) 예시:** ``` 0 0.5 0.5 0.3 0.4 1 0.7 0.3 0.2 0.3 ``` 형식: `class_id center_x center_y width height` (모든 좌표는 정규화된 값 0-1) ## 빠른 시작 - 대화형 모드 (권장) 인수 없이 실행하면 대화형 모드로 진입합니다: ```bash python yolo_annotation_modify.py ``` 대화형 모드에서는: 1. **데이터셋 선택**: 자동으로 찾은 YOLO 데이터셋 목록에서 선택하거나 직접 경로 입력 2. **작업 선택**: 메뉴에서 원하는 작업을 선택하고 여러 작업을 순차적으로 수행 가능 3. **저장**: 모든 작업 완료 후 결과를 저장 ### 대화형 모드 예시 ``` ============================================================ YOLO 어노테이션 편집기 - 대화형 모드 ============================================================ [1/3] 데이터셋 선택 ------------------------------------------------------------ 발견된 YOLO 데이터셋: 1. dataset/yolo 2. data/custom_dataset 0. 직접 경로 입력 데이터셋 번호 선택 (직접 입력은 0): 1 [+] 로딩 중: dataset/yolo [+] Found 150 label files ============================================================ Dataset: dataset/yolo ============================================================ 전체 통계: - 라벨 파일 수: 150 - 클래스 수: 3 클래스 상세: ID 클래스명 어노테이션 수 ------------------------------------------------------------ 0 person 450 1 car 320 2 truck 180 ------------------------------------------------------------ 합계 950 ============================================================ [2/3] 작업 선택 ------------------------------------------------------------ 사용 가능한 작업: 1. 클래스 제거 2. 클래스 통합 (병합) 3. 클래스 이름 변경 4. 클래스 ID 재할당 5. 현재 정보 표시 0. 완료 (저장 단계로) 작업 선택 (0-5): 2 현재 클래스: 0: person 1: car 2: truck 통합할 클래스 입력 (ID 또는 이름, 쉼표로 구분): 1,2 통합 후 클래스 이름 입력: vehicle [*] 'vehicle'로 통합 중: ['1', '2'] - 통합 대상: car (ID: 1) - 통합 대상: truck (ID: 2) [+] 'vehicle' (ID: 1)로 통합되었습니다 [+] 500개의 어노테이션이 변경되었습니다 작업 선택 (0-5): 0 [3/3] 결과 저장 ------------------------------------------------------------ 수행된 작업: 1. 통합: 1, 2 → vehicle [!] 주의: labels 폴더의 모든 .txt 파일이 수정됩니다. labels 폴더 백업 생성? (Y/n): Y [*] labels 폴더 백업 중... [+] 백업 생성됨: dataset/yolo/labels_backup_20250117_143025 data.yaml 백업 생성? (Y/n): Y [*] 저장 중... [+] data.yaml 백업 생성됨: dataset/yolo/data_backup_20250117_143026.yaml [+] data.yaml 저장 완료 ============================================================ 작업이 성공적으로 완료되었습니다! ============================================================ 데이터셋: dataset/yolo 설정 파일: dataset/yolo/data.yaml 라벨 파일: 150개 업데이트됨 ``` --- ## CLI 모드 사용법 명령행 인수를 사용하여 스크립트 방식으로도 실행할 수 있습니다. ### 1. 정보 확인 (info) 데이터셋의 전체 정보를 확인합니다. ```bash python yolo_annotation_modify.py info --dataset dataset/yolo ``` 출력 예시: ``` ============================================================ Dataset: dataset/yolo ============================================================ 전체 통계: - 라벨 파일 수: 150 - 클래스 수: 3 클래스 상세: ID 클래스명 어노테이션 수 ------------------------------------------------------------ 0 person 450 1 car 320 2 truck 180 ------------------------------------------------------------ 합계 950 ============================================================ ``` ### 2. 클래스 제거 (remove) 특정 클래스와 해당 어노테이션을 삭제합니다. **클래스 이름 또는 ID로 지정 가능**합니다. ```bash # 이름으로 클래스 제거 python yolo_annotation_modify.py remove \ --dataset dataset/yolo \ --classes "person,bicycle" # ID로 클래스 제거 python yolo_annotation_modify.py remove \ --dataset dataset/yolo \ --classes "0,5" # 이름과 ID 혼합 가능 python yolo_annotation_modify.py remove \ --dataset dataset/yolo \ --classes "0,bicycle,5" # 백업 생성 안 함 python yolo_annotation_modify.py remove \ --dataset dataset/yolo \ --classes "0,1" \ --no-backup ``` ### 3. 클래스 통합 (merge) 여러 클래스를 하나로 병합합니다. **클래스 이름 또는 ID로 지정 가능**합니다. ```bash # 이름으로 클래스 통합 python yolo_annotation_modify.py merge \ --dataset dataset/yolo \ --source "car,truck,bus,motorcycle" \ --target "vehicle" # ID로 클래스 통합 python yolo_annotation_modify.py merge \ --dataset dataset/yolo \ --source "1,2,3,4" \ --target "vehicle" # 이름과 ID 혼합 가능 python yolo_annotation_modify.py merge \ --dataset dataset/yolo \ --source "1,truck,3" \ --target "vehicle" # 백업 생성 안 함 python yolo_annotation_modify.py merge \ --dataset dataset/yolo \ --source "1,2,3" \ --target "vehicle" \ --no-backup ``` ### 4. 클래스 이름 변경 (rename) 클래스 이름을 변경합니다. **기존 클래스를 이름 또는 ID로 지정 가능**합니다. ```bash # 이름으로 클래스 이름 변경 python yolo_annotation_modify.py rename \ --dataset dataset/yolo \ --mapping "person:human,car:automobile" # ID로 클래스 이름 변경 python yolo_annotation_modify.py rename \ --dataset dataset/yolo \ --mapping "0:human,1:automobile" # 이름과 ID 혼합 가능 python yolo_annotation_modify.py rename \ --dataset dataset/yolo \ --mapping "0:human,car:automobile" ``` ### 5. 클래스 ID 재할당 (reindex) 클래스 ID를 순차적으로 재할당합니다. 클래스를 삭제하거나 통합한 후 ID를 정리할 때 유용합니다. ```bash # ID를 0부터 재할당 (YOLO 기본값) python yolo_annotation_modify.py reindex \ --dataset dataset/yolo # ID를 1부터 재할당 python yolo_annotation_modify.py reindex \ --dataset dataset/yolo \ --start 1 # 백업 생성 안 함 python yolo_annotation_modify.py reindex \ --dataset dataset/yolo \ --no-backup ``` ## 고급 사용 예시 ### 예시 1: 데이터셋 정리 워크플로우 ```bash # 1. 현재 상태 확인 python yolo_annotation_modify.py info --dataset dataset/yolo # 2. ID로 불필요한 클래스 제거 python yolo_annotation_modify.py remove \ --dataset dataset/yolo \ --classes "5,7,9" # 3. 유사 클래스 통합 python yolo_annotation_modify.py merge \ --dataset dataset/yolo \ --source "1,2,3" \ --target "vehicle" # 4. 클래스 이름 정리 python yolo_annotation_modify.py rename \ --dataset dataset/yolo \ --mapping "0:person,vehicle:car" # 5. ID 재할당 python yolo_annotation_modify.py reindex \ --dataset dataset/yolo \ --start 0 # 6. 최종 결과 확인 python yolo_annotation_modify.py info --dataset dataset/yolo ``` ### 예시 2: Train/Valid 데이터셋 동시 처리 YOLO 데이터셋의 경우 train과 val이 같은 data.yaml을 공유하므로, 한 번의 명령으로 모든 라벨 파일이 함께 업데이트됩니다: ```bash # 데이터셋 전체 클래스 이름 변경 (train/val 모두 자동 처리) python yolo_annotation_modify.py rename \ --dataset dataset/yolo \ --mapping "0:person,1:vehicle" ``` ### 예시 3: 대규모 클래스 통합 COCO 80개 클래스를 커스텀 클래스로 통합하는 예시: ```bash # 모든 vehicle 클래스를 하나로 통합 python yolo_annotation_modify.py merge \ --dataset dataset/yolo \ --source "car,truck,bus,motorcycle,bicycle" \ --target "vehicle" # 모든 animal 클래스를 하나로 통합 python yolo_annotation_modify.py merge \ --dataset dataset/yolo \ --source "cat,dog,bird,horse,cow" \ --target "animal" # ID 재정렬 python yolo_annotation_modify.py reindex \ --dataset dataset/yolo ``` ## Python 스크립트에서 사용 유틸리티를 Python 코드에서 직접 사용할 수도 있습니다. ```python from yolo_annotation_modify import YOLOAnnotationEditor # 데이터셋 로드 editor = YOLOAnnotationEditor('dataset/yolo') # 정보 확인 editor.print_info() # 작업 수행 (이름 또는 ID로 지정 가능) editor.remove_classes(['0', '1']) # ID로 제거 editor.remove_classes(['person', 'car']) # 이름으로 제거 editor.rename_classes({'0': 'human', 'car': 'automobile'}) # ID와 이름 혼합 가능 editor.reindex_classes(start_id=0) # 저장 (data.yaml만 저장, label 파일은 이미 수정됨) editor.save_yaml(backup=True) # 체이닝도 가능 editor = YOLOAnnotationEditor('dataset/yolo') editor.remove_classes(['5', '7']) \ .merge_classes(['1', '2'], 'vehicle') \ .reindex_classes(start_id=0) \ .save_yaml(backup=True) ``` ## 옵션 ### 백업 관련 기본적으로 labels 폴더와 data.yaml 파일 모두 백업이 생성됩니다. ```bash # 백업 생성 (기본값) python yolo_annotation_modify.py rename --dataset dataset/yolo --mapping "0:human" # 모든 백업 생성 안 함 python yolo_annotation_modify.py rename --dataset dataset/yolo --mapping "0:human" --no-backup # labels 폴더 백업만 생성 안 함 (data.yaml은 백업) python yolo_annotation_modify.py rename --dataset dataset/yolo --mapping "0:human" --no-labels-backup ``` 백업 파일명 형식: - Labels 폴더: `labels_backup_{YYYYMMDD_HHMMSS}/` - data.yaml: `data_backup_{YYYYMMDD_HHMMSS}.yaml` ## 주요 특징 ### ID와 이름 모두 지원 - 모든 작업(제거, 통합, 이름 변경)에서 클래스를 **ID 또는 이름**으로 지정 가능 - 숫자로 입력하면 자동으로 ID로 인식, 문자로 입력하면 이름으로 인식 - ID와 이름을 혼합하여 사용 가능 ### 어노테이션 통계 - 클래스별 어노테이션 개수 자동 계산 - 전체 어노테이션 합계 표시 - 실시간 정보 확인 가능 ### 자동 백업 - labels 폴더 전체 백업 - data.yaml 파일 백업 - 타임스탬프로 백업 파일 구분 ### 입력 오류 처리 - 잘못된 경로 입력 시 재입력 요청 - 잘못된 선택 입력 시 재입력 요청 - 존재하지 않는 클래스 ID/이름 입력 시 경고 표시 ## YOLO vs COCO 차이점 | 항목 | YOLO | COCO (MMDetection) | |------|------|---------------------| | 설정 파일 | data.yaml | JSON | | 클래스 ID | 0부터 시작 | 1부터 시작 | | 어노테이션 파일 | 이미지별 .txt 파일 | 단일 JSON 파일 | | 좌표 형식 | 정규화된 중심점+크기 | 픽셀 좌표 (bbox/polygon) | | 백업 대상 | labels 폴더 전체 + data.yaml | JSON 파일 하나 | ## 주의사항 1. **데이터 백업**: 중요한 데이터는 항상 백업 후 작업하세요. 2. **Train/Val 일치**: Train과 Val은 같은 data.yaml을 공유하므로 한 번의 작업으로 모두 수정됩니다. 3. **ID 순서**: `reindex` 명령은 기존 ID 순서를 기준으로 재할당합니다. 4. **병합 ID**: `merge` 명령은 가장 작은 ID를 새 카테고리 ID로 사용합니다. 5. **좌표 유지**: 모든 작업은 bounding box 좌표를 그대로 유지하고 클래스 ID만 수정합니다. 6. **파일 직접 수정**: label 파일(.txt)은 원본이 직접 수정되므로 반드시 백업을 생성하세요. ## 문제 해결 ### data.yaml을 찾을 수 없음 ```bash # 올바른 데이터셋 디렉토리 지정 (data.yaml이 있는 폴더) python yolo_annotation_modify.py info --dataset dataset/yolo # 절대 경로 사용 python yolo_annotation_modify.py info --dataset /full/path/to/dataset ``` ### label 파일 형식 오류 YOLO 형식 확인: ```python # 올바른 형식: class_id center_x center_y width height 0 0.5 0.5 0.3 0.4 1 0.7 0.3 0.2 0.3 ``` 모든 값은 0-1 사이의 정규화된 값이어야 합니다. ### data.yaml 형식 확인 ```yaml names: 0: class_name_1 1: class_name_2 2: class_name_3 train: images/train val: images/val ``` ## 라이선스 이 도구는 YOLO 형식 어노테이션 작업을 위한 유틸리티입니다.