7.13. Maksimum olmayanların bastırılması (Non-max suppression)

Bir tespit ağı, gerçek dünyadaki aynı nesnenin etrafında genellikle birkaç çakışan aday kutu üretir: nesneye yakın her bağlantı (anchor) benzer bir skorla tetiklenir ve son işlemci bunların hepsini görür. Maksimum olmayanların bastırılması (NMS), bu kümeyi tek bir kutuya dönüştüren adımdır.

Algoritma kısadır: aday kutuları skora göre sıralayın, en yüksek skorlu olanı alın, seçilen bir eşiğin ötesinde onunla çakışan diğer her kutuyu bastırın, ardından kalanlar arasından bir sonraki en yükseği alın ve tekrarlayın. Çakışma ölçütü kesişimin birleşime oranıdır (IoU) – iki kutunun ortak alanının, birleşik alanlarına bölünmesiyle elde edilen, 0 (çakışma yok) ile 1 (özdeş kutular) arasında bir değer. Sevk edilen her son işlemcide bulunan nms_threshold kurucu argümanı, kutuların hâlihazırda tutulan bir kutunun kopyaları olarak ele alındığı kesim noktasıdır.

Solda, tek bir özne etrafında 0.92, 0.83 ve 0.71 skorlarıyla etiketlenmiş üç çakışan sınırlayıcı kutu var. Bir ok sağı gösteriyor; orada 0.92 skoruyla hayatta kalan tek bir kutu kalmış. Daha düşük skorlu iki kutu, kesişimin birleşime oranı eşiği aştığı için daha yüksek skorlu kutu tarafından bastırılmış.

NMS, çakışan tespitlerden oluşan bir kümeyi en yüksek skorlu olana indirger.

7.13.1. Soft-NMS

Sevk edilen ml.utils.NMS sınıfı, çakışan bir kutunun skorunu tamamen düşürmek yerine, ne kadar çakıştığına bağlı bir miktarda azaltan bir iyileştirme olan Soft-NMS‘yi uygular. Düşürülen skor eşiğin altına inerse kutu atılır; aksi halde azaltılmış skorla hayatta kalır ve bir sonraki turda yarışır.

nms_sigma parametresi, azalmanın ne kadar agresif olacağını denetler. Küçük bir nms_sigma ile (sevk edilen varsayılan değer 0.1) azalma diktir: yoğun şekilde çakışan bir kutunun skoru neredeyse sıfıra çekilir ve Soft-NMS klasik NMS’ye indirgenir. Daha büyük bir nms_sigma ile azalma yumuşaktır ve farklı nesnelere ait çakışan kutular daha sık hayatta kalır; bu, aynı sınıftaki gerçek dünya nesneleri gerçekten çakıştığında (bir kalabalıktaki yüzler, bir avuç içi kümesi) önem taşır.

nms_sigma değerini <= 0 olarak ayarlamak azalmayı tamamen devre dışı bırakır: çakışan kutular orijinal skorlarıyla geçer ve onları yalnızca skor eşiği filtreler.

7.13.2. Doğrudan bir tane oluşturma

Sevk edilen her son işlemci, her çıkarım için yeni bir NMS oluşturur, her adayı buna ekler ve sonunda get_bounding_boxes() çağrısını yapar. Özel bir son işlemci aynı kalıbı izler:

from ml.utils import NMS

iw = model.input_shape[0][2]
ih = model.input_shape[0][1]

nms = NMS(iw, ih, inputs[0].roi)
for box, score, class_idx in candidates:
    nms.add_bounding_box(box.xmin, box.ymin,
                         box.xmax, box.ymax,
                         score, class_idx)
result = nms.get_bounding_boxes(threshold=nms_threshold,
                                sigma=nms_sigma)

Kurucu, ağın giriş genişliğini ve yüksekliğini piksel cinsinden ve modelin üzerinde çalıştığı orijinal görüntünün ROI’sini alır; add_bounding_box() kutu koordinatlarını bu ağ-girişi piksel uzayında alır ve get_bounding_boxes() hayatta kalanları ROI’yi kullanarak yeniden görüntü koordinatlarına eşler. Yeniden eşleme, Normalleştirme germesini otomatik olarak hesaba katar – kutuları geri yansıtmak için tahmin edicinin gördüğü aynı ROI kullanılır – böylece döndürülen kutular, yakalanan çerçeve üzerine çizilmeye hazırdır.

Döndürülen yapı, add_bounding_box öğesine geçirilen label_index ile indekslenen, sınıf başına listelerden oluşan bir listedir. Boş sınıf listeleri korunur, böylece indeks modelin sınıf indeksiyle eşleşir; enumerate(result) sınıfları tespitlerinin yanında dolaşır.