Ultralytics YOLO27: Bekleme listesine katıl.
Get Started
Dersorta düzey

Döndürülmüş Nesneler için Yönlendirilmiş Sınırlayıcı Kutular

Dört köşeli OBB'leri etiketle, DOTA8 üzerinde yolo26n-obb.pt eğit ve xywhr tahminlerini açı kurallarına takılmadan kararlı bir yönelim eksenine dönüştür.

Limanlardaki gemiler, bantlardaki kargolar ve yukarıdan görülen otoparklardaki arabalar aynı sorunu paylaşır: döndürülmüş ve sıkışık nesnelerin etrafındaki eksenlere hizalı kutular birbirleriyle örtüşür ve arka planı içine alır; bunun sonucunda NMS gerçek nesneleri siler ve sayım düşük çıkar. Yönlendirilmiş sınırlayıcı kutular her nesneye döndürülmüş bir dikdörtgen uydurur; bu, yoğun sahnelerde sayım sorununu çözer ve doğrudan bir açı bilgisi verir. Ancak açı, ilk entegrasyonların neredeyse hepsini zorlayan kuralları da beraberinde getirir — bu dersteki liman görüntüsünde ilk gemi −15° dönüş bildirirken gövdesi 75° boyunca uzanır.

Sonuç

dota8.yaml üzerinde yolo26n-obb.pt eğit, result.obb öğesinden sınıf başına algılama sayısını hesapla ve her tahminin xywhr değerini [0, 180) derece aralığında uzun kenar eksenine dönüştür.

Hızlı Başlangıç
Nasıl ilerleyeceğini zaten biliyorsan, işte kısa sürüm.
  1. Etiket satırı: sınıf, ardından çevre boyunca sıralanmış, normalize edilmiş dört köşe x1 y1 … x4 y4.

  2. yolo obb train data=dota8.yaml model=yolo26n-obb.pt epochs=1 imgsz=320.

  3. result.obb.xywhr (radyan cinsinden dönüş) veya .xyxyxyxy (köşeler) değerini oku; OBB sonuçları result.boxes değerini doldurmaz.

  4. Yönelimi uzun kenara göre normalize et: w < h olduğunda 90° ekle, ardından açının 180°'ye göre kalanını al.

Uygulamalı

Dönüş önemli olduğunda#

Havadan çekilmiş bir fotoğraftaki üç demirli yatın çevresine sıkıca oturan Ultralytics YOLO yönlendirilmiş sınırlayıcı kutuları; her biri Ship etiketi ve güven değeriyle gösteriliyor

Poz Tahmini ve OBB, algılama yerine OBB'nin ne zaman seçileceğini anlatır. Pratik test şu: komşu nesnelerin etrafındaki eksenlere hizalı sınırlayıcı kutular, nesnelerin kendilerinden daha fazla örtüşüyorsa NMS gerçek algılamaları baskılar ve sayım düşük çıkar. Havadan görüntüler bunun klasik örneğidir; önceden eğitilmiş yolo26n-obb.pt modelinin imgsz=1024 ile DOTA üzerinde eğitilmesinin nedeni de budur.

Eksenlere hizalı kutuYönlendirilmiş kutu
45° açıyla duran bir gemiye uydurulmuşyaklaşık yarısı arka plansıkı
Yoğun, döndürülmüş sıralarkutular örtüşür; NMS gerçek nesneleri silerkutular birbirinden net biçimde ayrılır
Açı verirhayırevet, eksen olarak (180°'ye göre kalan)
Sonuç alanıresult.boxesresult.obb

xyxyxyxy etiket biçimi#

Bir OBB etiket satırı, sınıf indeksinin ardından çevre boyunca sıralanmış, normalize edilmiş dört köşeden oluşur. Gerçek bir DOTA8 satırı (sınıf 1 ship değeridir):

1 0.813477 0.523437 0.814453 0.504882 0.87207 0.504882 0.87207 0.524414

Bunu dört nokta olarak oku: (0.813, 0.523) → (0.814, 0.505) → (0.872, 0.505) → (0.872, 0.524). Bu gemi neredeyse yatay durur; görüntünün yaklaşık 0.059'u kadar geniş ve 0.019'u kadar yüksektir. Ultralytics, her köşe kümesini minimum alanlı dikdörtgeni uydurarak merkez, genişlik, yükseklik ve dönüşe (xywhr) dönüştürür; böylece bir etiketleme aracından gelen hafifçe dikdörtgen olmayan bir dörtgenle bile eğitim yapılabilir. OBB veri kümesi kılavuzu biçimi açıklar; ultralytics.data.converter içindeki convert_dota_to_yolo_obb ise orijinal DOTA açıklamalarını dönüştürür.

DOTA8 havadan görüntüsünde tenis kortlarının, küçük araçların ve yüzme havuzunun çevresinde döndürülmüş kutular bulunan Ultralytics Platform açıklama düzenleyicisi

DOTA8 üzerinde eğit#

DOTA8, işlem hatlarını test etmek için oluşturulmuş küçük bir yönlendirilmiş kutu veri kümesidir:

Hava görüntüsü karolarından oluşan DOTA8 eğitim mozaiği: bağlı tekneler, tenis kortları, bir otopark ve aprondaki uçak sıraları; her nesnede yönlendirilmiş kutu ve sınıf indeksi bulunuyor

from ultralytics import YOLO

model = YOLO("yolo26n-obb.pt")
model.train(data="dota8.yaml", epochs=1, imgsz=320, device="cpu")
metrics = model.val()
print(f"OBB mAP50: {metrics.box.map50:.3f}  mAP50-95: {metrics.box.map:.3f}")
OBB mAP50: 0.995  mAP50-95: 0.832

OBB metrikleri metrics.box içinde yer alır, ancak bu metriklerin temelindeki IoU, döndürülmüş dikdörtgenler arasında hesaplanır.

DOTA8 bir duman testidir

DOTA8, ön eğitim verilerinin bir dilimi olduğu için puan yüksektir. Bu, iş hattının çalıştığını kanıtlar; kendi görüntülerin hakkında hiçbir şey söylemez.

Tahminleri oku ve açıyı normalleştir#

import math
from collections import Counter

from ultralytics import YOLO

def long_side_axis(w, h, r):
    """Angle of the box's long side in degrees, in [0, 180), whichever side the model called width."""
    deg = math.degrees(r) + (90 if w < h else 0)
    return deg % 180

model = YOLO("yolo26n-obb.pt")  # trained on DOTAv1, 15 aerial classes
result = model("https://ultralytics.com/images/boats.jpg", verbose=False)[0]
obb = result.obb.cpu()

print("xywhr:", tuple(obb.xywhr.shape), " xyxyxyxy:", tuple(obb.xyxyxyxy.shape))
print(Counter(result.names[int(c)] for c in obb.cls.tolist()))
for (cx, cy, w, h, r), conf in list(zip(obb.xywhr.tolist(), obb.conf.tolist()))[:5]:
    print(f"{conf:.2f} center=({cx:.0f},{cy:.0f}) size={w:.0f}x{h:.0f} raw={math.degrees(r):4.0f} deg  axis={long_side_axis(w, h, r):4.0f} deg")
xywhr: (173, 5)  xyxyxyxy: (173, 4, 2)
Counter({'ship': 168, 'harbor': 5})
0.87 center=(619,850) size=33x108 raw= -15 deg  axis=  75 deg
0.86 center=(1650,937) size=116x33 raw=  21 deg  axis=  21 deg
0.86 center=(1105,571) size=124x35 raw=  21 deg  axis=  21 deg
0.86 center=(1596,1037) size=129x35 raw=  25 deg  axis=  25 deg
0.86 center=(825,940) size=34x99 raw= -15 deg  axis=  75 deg

Satır satır:

  • xywhr: (173, 5) — her biri merkez x, merkez y, piksel cinsinden genişlik ve yükseklik ile radyan cinsinden dönüş açısı içeren 173 tespit. xyxyxyxy, aynı kutuları cv2.polylines için hazır dört köşe noktası olarak içerir.
  • Sayaç, result.obb.cls üzerinden sayım yapar: 168 gemi ve 5 liman. OBB modellerinde result.boxes, None olur; bu nedenle tespit için yazılmış sayım kodunda alanları değiştirmen gerekir.
  • raw ile axis karşılaştırması. İlk gemi −15° açıyla 33 × 108 boyutundadır: w kısa kenardır, bu nedenle gövde −15° + 90° = 75° boyunca uzanır. İkinci gemi 21° açıyla 116 × 33 boyutundadır ve uzun kenarı zaten ilk sıradadır. Ham açıları okursan ilk geminin ekseni 90° hatalı olur; normalleştirme sonrasında her geminin açısı aynı anlama gelir ve gemiler ile kareler arasında karşılaştırılabilir.

Kural, kurulu kaynak kodundan gelir: tahmin edilen dönüş açısı [−π/4, 3π/4) aralığındadır — yaklaşık −45° ile 135° arasıdır — ve aynı dikdörtgen (w, h, θ) veya (h, w, θ + 90°) olabilir. w değerinin uzun kenar olduğunu asla varsayma.

Küçük nesneler küçültme değil, karo kullanmayı gerektirir#

Havadan görüntülenen nesneler küçüktür; doğrulama veya dağıtım sırasında eğitimde kullanılan imgsz değerinin altına inmek, kısa sürede geri çağırma oranını düşürür. Modelin girişinden büyük uydu karolarını küçültmek yerine örtüşen karolara böl; yoksa 30 piksellik bir araba 5 piksellik bir lekeye dönüşür. SAHI karo çıkarımları kılavuzu bu tekniği gösteriyor; dedektör kullanılan bir otoyol karesinde tam görüntü çıkarımı, uzaktaki araçların çoğunu kaçırıyor:

Tam görüntü çıkarımından gelen tespitlerin yer aldığı, küçük ve uzaktaki araçların çoğunun kaçırıldığı otoyol karesi

Karo çıkarımı ise bunları bulur:

Aynı otoyol karesi; SAHI karo çıkarımı küçük ve uzaktaki araçların çok daha fazlasını tespit ediyor

Yaygın Hatalar#

Ön ve arka ayrımı yok

Belirti: Kareler arasında 180° dönen bir "yön" veya geriye doğru gidiyor gibi görünen gemiler. Neden: 180° döndürülmüş bir dikdörtgen yine aynı dikdörtgendir; bu nedenle OBB bir yön doğrultusu verir, ilerleme yönünü değil. Çözüm: Geminin veya forkliftin hangi yöne baktığını bilmen gerekiyorsa baş kısmına ya da çatal uçlarına bir poz anahtar noktası ekle veya kırpılmış görüntü üzerinde bir sınıflandırıcı kullan.

Ham doğrulama eğrilerini tespit çalıştırmalarıyla karşılaştırma

Belirti: Benzer verilerde OBB precision-recall eğrileri, tespit çalıştırmalarındakilerden farklı görünüyor. Neden: OBB doğrulaması varsayılan olarak conf=0.01 kullanırken diğer görevler 0.001 kullanır. Çözüm: mAP değerlerini karşılaştır veya eşleşen kesinlik-duyarlılık eğrilerine ihtiyacın varsa conf değerini açıkça ayarla.

Dene

obb.py komutunu çalıştır, ardından liman görüntüsündeki her geminin uzun kenar eksenini hesaplayan, en yaygın ekseni en yakın 10°'ye yuvarlayarak bulan ve bu eksenden 30°'den fazla sapan gemileri sayan bir betik yaz. 175° ile 5°'nin aralarında yalnızca 10° olduğunu unutma.

Tamamlanma ölçütü
Aşağıdakilerin tümü doğru olduğunda dersi tamamlamış olursun.
  • Betiğin gemi sayısını, en yaygın ekseni ve bu eksenden 30°'den fazla sapan gemilerin sayısını yazdırır.

  • Eksen karşılaştırman 180°'de döngüye girer; bu nedenle 175° ile 5° arasındaki fark 10° sayılır.

  • OBB'nin geminin başıyla kıçını neden ayırt edemediğini ve baş yönüne ihtiyaç duysaydın ne ekleyeceğini açıklayabilirsin.

Çözümü göster
import math
from collections import Counter

from ultralytics import YOLO

result = YOLO("yolo26n-obb.pt")("https://ultralytics.com/images/boats.jpg", verbose=False)[0]
axes = []
for (cx, cy, w, h, r), cls in zip(result.obb.xywhr.cpu().tolist(), result.obb.cls.tolist()):
    if result.names[int(cls)] == "ship":
        axes.append((math.degrees(r) + (90 if w < h else 0)) % 180)  # long-side axis in [0, 180)

def axis_gap(a, b):
    """Smallest difference between two axes; 175 and 5 degrees are only 10 apart."""
    d = abs(a - b) % 180
    return min(d, 180 - d)

common = Counter(round(a / 10) * 10 % 180 for a in axes).most_common(1)[0][0]
off = [a for a in axes if axis_gap(a, common) > 30]
print(f"{len(axes)} ships, most common axis ~{common} deg, {len(off)} more than 30 deg off it")
168 ships, most common axis ~20 deg, 32 more than 30 deg off it

Teknelerin çoğu yaklaşık 20° açıyla paralel duruyor; eksenden sapan 32 gemi, bir liman izleme kuralının inceleme için işaretleyeceği aykırı değerlerdir. Dikdörtgen 180° döndürmede simetrik olduğundan OBB geminin başıyla kıçını ayırt edemez; baş kısmına bir poz anahtar noktası eklemek gerçek baş yönünü verir.

Sırada ne var

Sırada, yerelleştirmeyi tamamen bırakıp tüm görüntüler ve kırpımlar için bir sınıflandırıcı eğitiyoruz.

İlerlemeni kaydetmek için giriş yap