Yolov kullanarak Object Detection çalışmaları yapmak istiyoruz. Bbox konusu işin olmazlarından. Ne işe yaradığına burada değinmenin bir anlamı yok. İnternette hakkında bilgi bir haylice. Bu yazının konusu şu aslında; elimiz de w1*u1 piksel değerlerinde görüntüler var ancak biz w2*u2 piksel değerlerine görüntüyü resize etmek istiyoruz fakat görüntülerin etiketleri yani bbox değerlerini yeni piksel değerlerine göre nasıl yeniden düzenleyebiliriz. Biraz matematik ile işi kolayca çözebiliriz. Meselenin özünü anladıktan sonra gerisi kolay.
Yolov bbox formatı olarak şunu kullanır; (C, x_center_normalized, y_center_normalized, width_normalized, height_normalized).
C: Objenin sınıf etiketi
x_center_normalized: Objenin x ekseninde merkez noktası normalize değeri
y_center_normalized: Objenin y ekseninde merkez noktası normalize değeri
width_normalized: Objenin normalize genişlik değeri
height_normalized: Objenin normalize yükseklik değeri
Aşağıda, bir görüntüde ki bbox kutusunun ne olduğu ve ilgili değerlerin neler olduklarını görsel üzerinden anlatmaya çalıştım.
Görüntüler sol üst köşeden başlar piksel değerlerini almaya. Yani sol üst köşe koordinat eksenimizin (0, 0) noktasıdır. Sağ alt köşe ise görüntümüzün sınır piksel değerleridir. Bir görüntü 930*930 piksel ise x ekseninde 930 piksel ve y ekseninde 930 piksel var demektir. Görüntünün içinde bir yerde yukarıda olduğu gibi kuş objesini tespit etmeye çalışan bir model geliştiriyor olduğumuzu düşünelim. Yolov çalışma mantığına göre tespit etmeye çalıştığımız nesnenin etrafına onu kapsayacak bir sınırlayıcı kutu (bbox) çizmemiz gerekir. Yani tespit etmek istediğin nesne görüntünün neresinde. Bir nevi koordinat bilgisi vermemiz icap ediyor. Yukarıda ki şekilde açıkça gözüktüğü gibi nesnemiz, bir köşesi (x1,y1), diğer köşesi (x2,y2) olan bir dörtgen içerisinde bulunmakta. Eğer ben x1, y1, x2 ve y2 değerlerini bilir isem Yolov’un benden istediği formata uygun değerleri kolaylıkla hesaplayabilirim.
Bbox’ın merkez noktasının koordinatları pek tabii yukarıda ki gibi hesaplanabilir. Ayrıca bbox’ın genişlik ve yükseklik değerleri de aşağıda ki gibi hesaplanabilir.
Fakat Yolov bizden bu değerlerin normalize edilmiş hallerini istemekte. Nasıl normalize edeceğiz! Pek tabiki x ekseninde ki değerlerimizi w_img’ye, y eksenin de ki değerlerimizi de h_img’ye bölerek. Aynı şekilde width ve height değerlerini de sıra ile w_img ve h_img’ ye bölmemiz gerekecek. Bu durumda denklemlerimizi şu şekilde yazmamız gerekecek.
Şimdi bir örnek yapalım. Görüntümüz aşağıdaki gibi 930*930 piksel bir görüntü olmuş olsun. Görüntü içinde bir gemimiz olsun ve biz o gemiyi tespit etmek istemiş olalım.
Yapmamız gereken bu geminin etrafını sınırlayacak bir dörtgen çizmek olacak ve bizde aşağıda ki gibi bir bbox çizmiş olalım.
x1= 485 y1= 140 x2= 576 y2= 415 w_img= 930 h_img= 930 (bu değerleri normalde programların kendisi hesap ediyor)
Bu durumda Yolov formatında bbox değerlerimiz şu şekilde olmuş oldu;
0 0.57043 0.298387 0.097849 0.295699
Başta ki “0” değeri gemiye vermiş olduğumuz sınıf etiketi idi. Yolov model eğitimi esnasında bu değerleri okuyup çözümleyerek görüntü içerisinde ki nesnenin nerede olduğu hakkında bilgi sahibi oluyor.
Peki buraya kadar bir bbox’ ın matematik arka planını anlamaya çalıştık, fakat diyelim ki görüntümüzü 768*768 piksel değerine resize etmek istediğimiz de yeni bbox değerlerini eski bbox değerlerinden nasıl türetebiliriz. Yazımızın konusu buydu hatırlarsanız. Zannımca konuyu buraya kadar anladı isek gerisini yapmak çok kolay olacaktır. İşlemleri tersine alarak elde edeceğimiz koordinat değerlerini scale ederek yeniden bbox değerlerini hesaplamamız gerekecek.
Bu defa elimizde (0 0.57043 0.298387 0.097849 0.295699) değerleri var. Yapmamız gereken aşağıda ki formülleri kullanmak. (formüllerin nasıl türetildiğine değinmeyeceğim, matematik işlemleri tersine çevirdiğimizi düşünün)
Bu denklem yardımı ile görüntümüzde ki bbox’ın köşe koordinat değerlerini elde etmiş olduk. Bundan sonra yapılması gereken, görüntüyü hangi oranda resize etti isek aynı oranda bu değerleri de bir nevi resize etmek.
Bundan sonrası artık en baştan anlattığım şekilde ilerleyecek. Biz yeni x1, x2, y1 ve y2 değerlerini elde etmiş olduk ve yeni görüntünün piksel değerini de biliyoruz. İlk başta ki formülleri kullanarak yeni bbox değerlerini elde edebiliriz artık.
Bu işlemleri bizim için yapabilen bir Python betiğini buraya ekliyorum.
import cv2 import os # Dosya yolları image_folder = r'E:\veri setleri\Optical Satellite Datasets\ShipRSImageNet_V1\Yolov_Format\images_930' label_folder = r'E:\veri setleri\Optical Satellite Datasets\ShipRSImageNet_V1\Yolov_Format\labels_930' output_image_folder = r'E:\veri setleri\Optical Satellite Datasets\ShipRSImageNet_V1\Yolov_Format\images_768' output_label_folder = r'E:\veri setleri\Optical Satellite Datasets\ShipRSImageNet_V1\Yolov_Format\labels_768' # Eski ve yeni boyutlar old_size = 930 new_size = 768 scale = new_size / old_size # Çıktı klasörlerini oluştur os.makedirs(output_image_folder, exist_ok=True) os.makedirs(output_label_folder, exist_ok=True) # Görüntü ve label dosyalarını işleme for image_name in os.listdir(image_folder): # Görüntü dosyasını oku image_path = os.path.join(image_folder, image_name) image = cv2.imread(image_path) # Görüntüyü bicubic interpolasyonu ile yeniden boyutlandır resized_image = cv2.resize(image, (new_size, new_size), interpolation=cv2.INTER_CUBIC) resized_image_path = os.path.join(output_image_folder, image_name) cv2.imwrite(resized_image_path, resized_image) # Label dosyasını oku label_name = image_name.replace('.bmp', '.txt') label_path = os.path.join(label_folder, label_name) if os.path.exists(label_path): with open(label_path, 'r') as f: lines = f.readlines() updated_lines = [] for line in lines: parts = line.strip().split() label = parts[0] x_center = float(parts[1]) y_center = float(parts[2]) width = float(parts[3]) height = float(parts[4]) # x1, y1, x2, y2 hesapla x1 = (x_center - width / 2) * old_size y1 = (y_center - height / 2) * old_size x2 = (x_center + width / 2) * old_size y2 = (y_center + height / 2) * old_size # Yeni x1, y1, x2, y2 değerlerini ölçekle x1_new = x1 * scale y1_new = y1 * scale x2_new = x2 * scale y2_new = y2 * scale # Yeni bbox değerlerini normalize et x_center_new = ((x1_new + x2_new) / 2) / new_size y_center_new = ((y1_new + y2_new) / 2) / new_size width_new = (x2_new - x1_new) / new_size height_new = (y2_new - y1_new) / new_size # Güncellenmiş etiketi kaydet updated_lines.append(f"{label} {x_center_new:.6f} {y_center_new:.6f} {width_new:.6f} {height_new:.6f}\n") updated_label_path = os.path.join(output_label_folder, label_name) with open(updated_label_path, 'w') as f: f.writelines(updated_lines) print("Tüm görüntüler ve etiketler başarıyla güncellendi!")
Kolay gele…
İlk Yorumu Siz Yapın