hitit-cuneiform-ocr / code /convert_and_merge.py
savastakan's picture
Initial upload: code + 5 record checkpoints + fuse
f211247 verified
Raw
History Blame Contribute Delete
6.97 kB
#!/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()