#!/usr/bin/env python3 """ 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: # .2 versiyonlarını atla 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] # "(1)" suffix'lerini temizle 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]) # center x (normalized) cy = float(parts[2]) # center y (normalized) w = float(parts[3]) # width (normalized) h = float(parts[4]) # height (normalized) # YOLO center format -> top-left corner (pixel coords) 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 yükle label_dict = load_label_dict(DICT_FILE) print(f"Label dict: {len(label_dict)} sınıf yüklendi") # Tablet-resim eşleşmesi tablet_map = get_tablet_image_map() print(f"Mevcut tablet sayısı: {len(tablet_map)}") # Her label dosyasını işle 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) # Label dosyası boş mu? if os.path.getsize(label_path) == 0: print(f" SKIP: {label_file} - boş label dosyası (tablet {tablet_id})") skipped += 1 continue try: # Resim boyutlarını al img = Image.open(img_path) img_w, img_h = img.size img.close() # YOLO -> annotations dönüşümü result = yolo_to_annotations(label_path, img_w, img_h, label_dict, tablet_id) # .3 versiyonu olarak kaydet (YOLO'dan dönüştürülmüş) output_folder = os.path.join(TABLET_DIR, f"{tablet_id}.3") os.makedirs(output_folder, exist_ok=True) # Resmi sembolik link olarak ekle (kopyalamaya gerek yok) 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.txt kaydet 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}") # Toplam istatistik 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()