| |
| """ |
| YOLO format label dosyalarını mevcut cozumlenmis_tabletler formatına (.2 annotations) dönüştürür |
| ve birleştirir. |
| |
| YOLO format: class_id center_x center_y width height (normalized 0-1) |
| Hedef format (.2): {"TabletId": N, "annotations": [{"id": "...", "lang": "Hititçe", |
| "mark": {"x": px, "y": px, "type": "RECT", "width": px, "height": px}, |
| "pk_id": N, "col_no": 0, "row_no": N, "comment": "sign_name"}]} |
| """ |
|
|
| import json |
| import os |
| import re |
| import random |
| import string |
| from PIL import Image |
|
|
| BASE_DIR = "/arf/scratch/stakan/hitit-proje" |
| TABLET_DIR = os.path.join(BASE_DIR, "datasets" / "sources" / "hitit_local") |
| LABEL_DIR = os.path.join(BASE_DIR, "yeni_veri/labels") |
| DICT_FILE = os.path.join(BASE_DIR, "yeni_veri/label_dict.txt") |
|
|
| def load_label_dict(path): |
| """label_dict.txt dosyasını yükle: class_id -> sign_name""" |
| d = {} |
| with open(path) as f: |
| for line in f: |
| line = line.strip() |
| if ':' in line: |
| cid, name = line.split(':', 1) |
| d[int(cid.strip())] = name.strip() |
| return d |
|
|
| def random_id(length=6): |
| """Rastgele annotation ID üret""" |
| return ''.join(random.choices(string.ascii_letters + string.digits, k=length)) |
|
|
| def find_image_in_folder(folder_path): |
| """Klasördeki resim dosyasını bul""" |
| for f in os.listdir(folder_path): |
| if f.lower().endswith(('.jpg', '.jpeg', '.png', '.gif', '.bmp')): |
| return os.path.join(folder_path, f) |
| return None |
|
|
| def get_tablet_image_map(): |
| """Resim adı (stem) -> (tablet_id, folder_path, image_path) eşleşmesi""" |
| mapping = {} |
| for folder in os.listdir(TABLET_DIR): |
| if '.' in folder: |
| continue |
| folder_path = os.path.join(TABLET_DIR, folder) |
| if not os.path.isdir(folder_path): |
| continue |
| img_path = find_image_in_folder(folder_path) |
| if img_path: |
| img_name = os.path.basename(img_path) |
| stem = os.path.splitext(img_name)[0] |
| |
| clean_stem = re.sub(r'\s*\(\d+\)', '', stem) |
| mapping[clean_stem] = { |
| 'tablet_id': folder, |
| 'folder_path': folder_path, |
| 'image_path': img_path |
| } |
| return mapping |
|
|
| def yolo_to_annotations(label_path, img_width, img_height, label_dict, tablet_id): |
| """YOLO label dosyasını annotations formatına dönüştür""" |
| annotations = [] |
| |
| with open(label_path) as f: |
| lines = f.readlines() |
| |
| for row_no, line in enumerate(lines, 1): |
| parts = line.strip().split() |
| if len(parts) < 5: |
| continue |
| |
| class_id = int(parts[0]) |
| cx = float(parts[1]) |
| cy = float(parts[2]) |
| w = float(parts[3]) |
| h = float(parts[4]) |
| |
| |
| px_x = (cx - w/2) * img_width |
| px_y = (cy - h/2) * img_height |
| px_w = w * img_width |
| px_h = h * img_height |
| |
| sign_name = label_dict.get(class_id, f"class_{class_id}") |
| |
| annotation = { |
| "id": random_id(), |
| "lang": "Hititçe", |
| "mark": { |
| "x": round(px_x, 2), |
| "y": round(px_y, 2), |
| "type": "RECT", |
| "width": round(px_w, 2), |
| "height": round(px_h, 2) |
| }, |
| "pk_id": row_no, |
| "col_no": 0, |
| "row_no": row_no, |
| "comment": sign_name |
| } |
| annotations.append(annotation) |
| |
| return { |
| "TabletId": int(tablet_id) if tablet_id.isdigit() else tablet_id, |
| "annotations": annotations |
| } |
|
|
| def main(): |
| print("=" * 60) |
| print("YOLO -> Annotations Format Dönüştürücü & Birleştirici") |
| print("=" * 60) |
| |
| |
| label_dict = load_label_dict(DICT_FILE) |
| print(f"Label dict: {len(label_dict)} sınıf yüklendi") |
| |
| |
| tablet_map = get_tablet_image_map() |
| print(f"Mevcut tablet sayısı: {len(tablet_map)}") |
| |
| |
| converted = 0 |
| skipped = 0 |
| errors = 0 |
| |
| for label_file in sorted(os.listdir(LABEL_DIR)): |
| if not label_file.endswith('.txt'): |
| continue |
| |
| stem = os.path.splitext(label_file)[0] |
| clean_stem = re.sub(r'\s*\(\d+\)', '', stem) |
| |
| info = tablet_map.get(clean_stem) |
| if not info: |
| print(f" SKIP: {label_file} - tablet bulunamadı") |
| skipped += 1 |
| continue |
| |
| tablet_id = info['tablet_id'] |
| img_path = info['image_path'] |
| label_path = os.path.join(LABEL_DIR, label_file) |
| |
| |
| if os.path.getsize(label_path) == 0: |
| print(f" SKIP: {label_file} - boş label dosyası (tablet {tablet_id})") |
| skipped += 1 |
| continue |
| |
| try: |
| |
| img = Image.open(img_path) |
| img_w, img_h = img.size |
| img.close() |
| |
| |
| result = yolo_to_annotations(label_path, img_w, img_h, label_dict, tablet_id) |
| |
| |
| output_folder = os.path.join(TABLET_DIR, f"{tablet_id}.3") |
| os.makedirs(output_folder, exist_ok=True) |
| |
| |
| img_basename = os.path.basename(img_path) |
| img_link = os.path.join(output_folder, img_basename) |
| if not os.path.exists(img_link): |
| os.symlink(img_path, img_link) |
| |
| |
| mark_path = os.path.join(output_folder, "mark.txt") |
| with open(mark_path, 'w') as f: |
| json.dump(result, f, ensure_ascii=False) |
| |
| ann_count = len(result['annotations']) |
| print(f" OK: tablet {tablet_id}.3 <- {label_file} ({ann_count} anotasyon, {img_w}x{img_h})") |
| converted += 1 |
| |
| except Exception as e: |
| print(f" ERROR: {label_file} - {e}") |
| errors += 1 |
| |
| print(f"\n{'=' * 60}") |
| print(f"SONUÇ:") |
| print(f" Dönüştürülen: {converted}") |
| print(f" Atlanan: {skipped}") |
| print(f" Hata: {errors}") |
| |
| |
| total_folders = len([d for d in os.listdir(TABLET_DIR) if os.path.isdir(os.path.join(TABLET_DIR, d))]) |
| total_files = sum(len(files) for _, _, files in os.walk(TABLET_DIR)) |
| print(f"\n Toplam klasör: {total_folders}") |
| print(f" Toplam dosya: {total_files}") |
|
|
| if __name__ == '__main__': |
| main() |
|
|