Ez az alfejezet a detektálási feladat első matematikai rétegét építi
fel: hogyan adjuk meg egy objektum helyét egy képen, hogyan mérjük két
doboz átfedését, és hogyan fogalmazzuk meg a lokalizációt regressziós
célként. A 22.1. Adateredet, címke és csoportos
split egység rögzítette a GlyphLab annotációs szerződését: a
metadata.csv minden képhez
xmin, ymin, xmax, ymax oszlopot ad, és a doboz a maszk
legkisebb befoglaló téglalapja. A 25.1. Teljes
képosztályozó adatfolyam adatfolyama a képosztályozó
bemeneti–kimeneti alakjait rögzítette; most ehhez a lokalizációs
kimenetet adjuk hozzá. A 14.1. Stride, padding,
dilation és outputméret határkezelési leckéje itt is közvetlenül
hasznosul: ugyanaz a fél-nyílt tartománygondolat, amely az outputablak
érvényességét definiálta, a doboz pixelhalmazát is meghatározza. A
CNN-gerincet és operátorát a 14.4. Csoportos és
depthwise konvolúció és 16.4. IV. ellenőrző
pont: a CNN-operátor teljes megértése egységekből ismerjük; a
detektálási fej arra a feature mapra épül. A 22.4.
Augmentációs kísérlet és domainváltozás és 23.4.
Hibaszeletek és alkalmazási határ módszertani korlátai
figyelmeztetnek: a clean és corrupt kiértékelést, valamint a szeletekre
bontott hibajelentést a detektálási metrikáknál is meg kell tartani, míg
a 25.4. Nyílt halmaz és ismeretlen input nyílt
halmaz logikája szerint a lokalizáció önmagában nem dönti el, hogy a
dobozban tényleg ismert objektum van-e.
Induló kérdés. Két doboz: és . Hány közös pixelük van a fél-nyílt konvenció szerint, és mennyi lenne ugyanez zárt intervallumos számolással? Becslését a 3. szakasz lemmája után ellenőrizheti.
Definíció (tengelypárhuzamos doboz, xyxy). Egy tengelypárhuzamos doboz négy valós koordinátája
ahol és . A doboz mint ponthalmaz a fél-nyílt Descartes-szorzat:
A sorrend a könyv egészében xmin, ymin, xmax, ymax;
ugyanez a GlyphLab metadata.csv oszlopsorrendje. Diszkrét
raszteren a
oszlopindex a
,
az
sorindex a
fél-nyílt cellának felel meg. Így a doboz pontosan azokat a pixeleket
foglalja magában, amelyekre
és
.
Definíció (terület). A doboz területe
A definíció pozitivitása miatt pozitív. A fél-nyílt határválasztás a kontinuum területen nem változtat az értéken, a raszteren viszont pontosan a cellák számát adja: az intervallum egész cellát tartalmaz, ha a határok egész indexek.
A GlyphLab maszkjában például ha a foreground pixelek oszlopai , akkor a doboz vízszintes vetülete , hossza 4 pixel; a már nem tartozik bele.
Normalizált koordináták. Legyen a kép szélessége , magassága ; a GlyphLabon . A normalizált doboz
és a hozzá tartozó ponthalmaz . A normalizált terület . A normalizálás a modell bemeneti skálájához igazítja a célokat; a 3. szakaszban bizonyítjuk, hogy közös skálázás alatt az IoU nem változik.
Tensoralak. Egy
dobozból álló batch reprezentációja
,
minden sor egy [xmin,ymin,xmax,ymax] vektor, float32. A
gyakorlatban a dobozregressziós cél is float32, akkor is, ha a
beolvasott annotáció egész.
Lemma 3.1 (két fél-nyílt doboz metszete). Legyen és , ahol és (). Vezessük be az
jelöléseket. Ha és , akkor
különben .
Bizonyítás. Egy pont pontosan akkor eleme -nek, ha mindkét koordinátájára mindkét doboz fél-nyílt feltétele teljesül:
Az -feltételpár ekvivalens a egyenlőtlenséggel. Ez pontosan akkor ír le nemüres intervallumot, ha ; egyébként nincs olyan , amely mindkét dobozban benne van. Ugyanígy az -feltétel a intervallumot adja, ha . A síkbeli metszet a két koordinátavetület Descartes-szorzata, tehát pontosan akkor nemüres, ha mindkét és teljesül, és ekkor . ∎
Következmény 3.2. A Lemma 3.1 feltételei mellett a metszet területe
ahol a éppen az üres esetet kódolja.
Definíció (IoU, Intersection over Union). Két pozitív területű doboz átfedési aránya
ahol a metszetet a Lemma 3.1 definiálja. Az unió területét a szitaformulával számoljuk:
Az üres metszet esetén a számláló , a nevező pedig , tehát jól definiált.
Tulajdonságok. Pozitív területű dobozokra:
Az 1. és 2. állítás közvetlenül a metszet szimmetriájából és a nemnegatív területből következik. A 3. állításhoz: ha , akkor a metszet és az unió területe egyenlő. Megfordítva, ha , akkor ; mivel a metszet részhalmaza az uniónak, és a terület a fél-nyílt téglalapokon additív, a különbséghalmaz területe nulla. Két pozitív területű tengelypárhuzamos doboz különbsége csak akkor lehet nulla területű, ha a dobozok ponthalmazként egybeesnek. A 4. állítást külön lemmaként igazoljuk.
Lemma 3.3 (skálainvariancia). Legyen , ahol . Pozitív területű dobozokra
Bizonyítás. lineáris bijekció, ezért halmazművelettel felcserélhető: és . A terület skálázódását a lineáris leképezés determinánsa adja: minden dobozterület, így a metszet és az unió területe is -nal szorzódik. A hányadosban a pozitív közös tényező kiesik. A normalizált koordináták éppen a , eset. ∎
Kézi példa. Legyen és . Ekkor , , tehát a metszet , területe . A területek , ; az unió ; így . Az induló kérdésben szereplő és esetén a metszet , amely a 3. sor és 3. oszlop egyetlen cellája; a fél-nyílt IoU tehát . A zárt számolás a 3. és 4. sort/oszlopot is közösnek venné, ami négy cellát és adna.
A detektálási fej feladata nem a négy xyxy koordináta közvetlen kiadása, hanem egy regressziós delta előrejelzése egy rögzített hivatkozási dobozhoz, az úgynevezett anchorhoz vagy proposalhoz képest. A célokat középpontos paraméterezésben adjuk meg: az xyxy dobozból
és a visszafelé konverzió , , , . Legyen az anchor , a ground truth pedig . A céldelta komponensei:
A hálózat kimenete ugyanezen a skálán él, és a dekódolás
Az exponenciális miatt a dekódolt mindig pozitív, tehát a dekódolás mindig érvényes , dobozt ad. A nincs korlátozva: a középpont elhagyhatja a képet; ennek kezelése a detektor utófeldolgozásához tartozik (26.2. Egy- és kétlépcsős detektor).
Két érv szól a normalizálás mellett. Egyrészt a -val osztott középponteltolás mértékegységet vált: a azt jelenti, hogy a célközéppont az anchor szélességének tizedével jobbra van, függetlenül a pixelmérettől. Másrészt a szélesség logaritmusa a relatív hibát szimmetrizálja: a kétszeres túllövés és a feleakkora alullövés egyaránt delta-hibát ad. Ez a választás a [P12] nyomán elterjedt családba tartozik; a hivatkozott cikk teljes módszerszakaszának újraolvasása a kézirat jelen állapotában még nem történt meg, ezért a pontos megegyezést a fejezetvégi ellenőrzési listán jelöljük.
Lokalizációs loss. A predikált és a cél közötti komponensenkénti veszteség a smooth L1 függvény, küszöbbel:
A választással a kis hibákra kvadratikus, nagy hibákra lineáris a büntetés; a gradiens esetén , azon kívül . Ez robusztusabb az L2-nél, mert egy durva kiugró dobozhiba nem dominálja a batch gradienst, ugyanakkor a nemdifferenciálhatóságát is kisimítja a nullában. A lokalizációs loss egy pozitív objektumokból álló halmaz felett
és , ha üres. A cél csak akkor értelmes, ha az -edik javaslathoz tényleges objektum tartozik; háttérjavaslatra nincs definiált dobozregressziós cél. Az osztály- és objektumossági loss ettől külön tag, amelyet a detektorarchitektúrák tárgyalásakor (26.2. Egy- és kétlépcsős detektor) adunk hozzá.
Kézi cél- és loss-példa. Anchor , ground truth . A cél , , . Ha a hálózat -t ad, akkor -gyel
A dekódolt predikció , ami a célhoz képest középponthibát ad; a méretek és .
A labor a lab munkakönyvtárból futtatandó, ahol a
data/images.npy, data/masks.npy,
data/metadata.csv és data/manifest.json fájlok
a kezdőlabor szerződésének megfelelően vannak jelen. Az adatgenerálás
seedje 20261020; a dobozszámítás maga determinisztikus,
ezért új seedet nem állítunk be. A mask uint8, a doboz
float32, a számítás CPU-n történik.
# lab/n101_lab.py
import csv
import numpy as np
masks = np.load("data/masks.npy") # (360,1,24,24) uint8
print(f"masks shape: {masks.shape}, dtype: {masks.dtype}")
def mask_to_box(mask: np.ndarray) -> np.ndarray:
"""A foreground pixelek legkisebb fél-nyílt xyxy befoglaló doboza."""
ys, xs = np.nonzero(mask[0])
if len(xs) == 0:
raise ValueError("üres maszk")
return np.array([xs.min(), ys.min(), xs.max() + 1, ys.max() + 1],
dtype=np.float32)
def box_iou(a: np.ndarray, b: np.ndarray) -> float:
"""Két [xmin,ymin,xmax,ymax] fél-nyílt doboz IoU-ja."""
ix0, iy0 = max(a[0], b[0]), max(a[1], b[1])
ix1, iy1 = min(a[2], b[2]), min(a[3], b[3])
inter = max(0.0, ix1 - ix0) * max(0.0, iy1 - iy0)
area = lambda z: (z[2] - z[0]) * (z[3] - z[1])
union = area(a) + area(b) - inter
return float(inter / union) if union > 0 else 0.0
with open("data/metadata.csv", newline="", encoding="utf-8") as f:
meta = list(csv.DictReader(f))
max_err = 0.0
for row in meta:
idx = int(row["index"])
computed = mask_to_box(masks[idx])
ref = np.array([float(row[k]) for k in ("xmin", "ymin", "xmax", "ymax")],
dtype=np.float32)
err = float(np.max(np.abs(computed - ref)))
max_err = max(max_err, err)
print(f"metadata doboz max abs hiba: {max_err:.6f}")
assert max_err == 0.0
a = np.array([10.0, 5.0, 20.0, 15.0], dtype=np.float32) # [10,20)x[5,15)
b = np.array([15.0, 10.0, 25.0, 20.0], dtype=np.float32) # [15,25)x[10,20)
iou_ab = box_iou(a, b)
print(f"kézi IoU: {iou_ab:.6f} (elvárt: {1/7:.6f})")
assert abs(iou_ab - 1/7) < 1e-6
c = np.array([0.0, 0.0, 10.0, 10.0], dtype=np.float32)
d = np.array([10.0, 0.0, 20.0, 10.0], dtype=np.float32)
print(f"érintkező IoU: {box_iou(c, d):.6f} (elvárt: 0.0)")
assert box_iou(c, d) == 0.0Futtatási parancs: python n101_lab.py. A c
és d dobozok érintkeznek, mert az első vízszintes vetülete
,
a másodiké
;
a közös határ nincs benne a fél-nyílt intervallumokban, ezért az IoU
nulla. A kód itt nincs futtatva; a fenti kimeneti sorok a maszk- és
metadata-definícióból számított várt értékek, nem mért futási
jegyzőkönyv.
F1 (fogalmi, nehézség 1). Magyarázza el, miért nem közömbös, hogy a dobozokat fél-nyílt vagy zárt intervallumként reprezentáljuk, amikor az IoU-t diszkrét pixelrácson számoljuk. Adjon konkrét dobozpárt, amelyre a két konvenció eltérő IoU-t ad.
F2 (levezetési, nehézség 2). Legyen és . A Lemma 3.1 segítségével adja meg a metszetet, a területeket, az uniót és az IoU-t. Igazolja a 3.3 Lemma állítását ezen a konkrét páron úgy, hogy mindkét dobozt -szeresére skálázza.
F3 (implementációs, nehézség 2). Írjon
NumPy-függvényt box_iou_batch(A, B) néven, amely
és
bemenetből az
IoU-mátrixot adja. Vektorizált megoldást adjon; ellenőrizze az
,
esetre az elvárt mátrixot
tűréssel.
F4 (hibakeresési, nehézség 1). Az alábbi függvény egyetlen pixelre szóló maszkból rossz dobozt ad:
def mask_to_box_bug(mask):
ys, xs = np.nonzero(mask[0])
return np.array([xs.min(), ys.min(), xs.max(), ys.max()], dtype=np.float32)Lokalizálja a hibát, mutassa meg következményét egy egycellás maszkon, és adja meg a javítást.
F5 (kísérleti/transzfer, nehézség 3). Tervezzen kis kísérletet a GlyphLab adaton a smooth L1 küszöbének kiválasztására egy rögzített anchorú, egyobjektumos dobozregressziós fejhez. Adja meg a kérdést, a baseline-t, a splitet, a metrikát, a választási szabályt, az erőforrásigényt és a következtetés érvényességi határát. Az eredményt előre ne rögzítse.
F1. A fél-nyílt intervallum a raszteren pontosan a darab egész cellát fedi, a zárt pedig darabot, ha egész határokkal dolgozunk. Az IoU ezért függ a konvenciótól, ahogy a 3. szakasz példája mutatja: négy cellát, szintén négy cellát fed, és fél-nyílt konvencióban diszjunktak, tehát . Zárt konvencióban mindkettő kilenc cellát fedne, a közös 3. sor és oszlop egy cellát adna, így . Ugyanaz a képpár tehát más metrikát ad; a keverés off-by-one eltérést okoz.
F2. A metszet: , , , ; és , tehát a metszet , területe . A területek , ; az unió ; az IoU . A -szeres skálázás után a metszet , területe ; az unió ; a hányados , tehát változatlan.
F3. A vektorizált megoldás shape-logikája:
A[:, None, :] alakja
,
B[None, :, :] alakja
,
így a kivonásaik
-re
broadcastolódnak.
import numpy as np
def box_iou_batch(A, B):
lt = np.maximum(A[:, None, :2], B[None, :, :2])
rb = np.minimum(A[:, None, 2:], B[None, :, 2:])
inter = np.prod(np.maximum(rb - lt, 0.0), axis=-1)
area = lambda X: (X[:, 2] - X[:, 0]) * (X[:, 3] - X[:, 1])
union = area(A)[:, None] + area(B)[None, :] - inter
return inter / union
A = np.array([[0,0,10,10],[20,20,30,30]], dtype=np.float32)
B = np.array([[5,5,15,15],[21,21,31,31],[0,0,10,10]], dtype=np.float32)
print(box_iou_batch(A, B))Az elvárt mátrix: az első sorban a -es doboz a -tel , a -gyel , önmagával ; a második sorban a -as doboz rendre , , .
F4. A hiba az xmax=xs.max() és
ymax=ys.max() hiányzó
.
Egyetlen, a 12. oszlopban és 12. sorban álló maszkra a hibás függvény
[12,12,12,12]-t ad, amelynek xmax-xmin=0 és
ymax-ymin=0, tehát területe nulla; a doboz üres, és az IoU
számlálója is nulla lesz, még akkor is, ha két ugyanilyen egycellás
maszk dobozát hasonlítjuk össze. A javítás xs.max()+1 és
ys.max()+1; ezzel a doboz [12,13)x[12,13),
területe
,
és önmagával vett IoU-ja
.
F5. Megoldásminta. Kérdés: a küszöb hogyan hat a GlyphLab dobozregressziós fej val- és test-IoU-jára? Adat és split: a rögzített GlyphLab train/val/test split; a maszkból minden képhez egy ground truth doboz. Modell és cél: a 25.1. Teljes képosztályozó adatfolyam alfejezetben ismertetett kis CNN-gerinc után egy 4 dimenziós fej; az anchor legyen a train dobozok átlagos középpontos doboza, az objektumosság oldható meg a maszkból, így minden kép pozitív. Változó tényező: csak ; minden más hiperparaméter rögzített. Baseline: a train ground truth dobozok konstans átlaga, képenkénti IoU-ban mérve. Metrika: képenkénti IoU átlaga; a tesztet egyszer, a val szerinti legjobb checkpointkal értékeljük. Ismétlés: három training seed; a jelentéshez a seedek közötti szórást is közöljük. Erőforrás: kis CPU, float32, a kísérlet néhány perc futásidő nagyságrendű lehet ezen a méreten. Érvényességi határ: a GlyphLab procedurális adat, nem természetes képi benchmark; a sorrendje nem vihető át általános detektálási adatra, és a konstans-anchor konstrukció nem méri a detektor proposal-minőségét.
Tipikus tévedés. A pixelinclusive és fél-nyílt
koordináták keverése off-by-one hibát ad. Az érintkező
és
dobozok fél-nyílt konvencióban diszjunktak; ha valaki a metszetet
helyett egy közös oszlopként kezeli, hamis pozitív átfedést mér. A labor
c/d esete pontosan ezt a helyzetet
ellenőrzi.
Önellenőrzés. (1) A box_iou függvény
üres metszetre 0-t ad, nem pedig negatív területet? (2) A normalizált és
pixelkoordinátás IoU ugyanazt az értéket adja a 3.3 Lemma alapján? (3) A
mask_to_box üres maszkra kivételt dob, nem néma nulla
dobozt? (4) A céldelta dekódolása visszaadja a ground truth dobozt a
esetben?
Visszahívás. A 14.1. Stride, padding, dilation és outputméret outputméret-levezetésében az érvényes ablakot ugyanilyen fél-nyílt indexfeltétellel definiáltuk: az ablak minden mintavételi pontjának a megengedett tartományba kell esnie, és a szélső határ már nem tartozik a halmazhoz. Ez a szemlélet itt a dobozok pixelhalmazára költözött át.
A tengelypárhuzamos doboz fél-nyílt pozitív területű halmaz, xyxy sorrendben. Két doboz metszete a koordinátánkénti – vetület, ha és , különben üres; területe . Az IoU a metszet és az unió területének hányadosa, üres metszetre nulla, és közös pozitív skálázásra invariáns. A dobozregresszió normalizált, log-skálázott deltákat tanul anchorhoz képest, smooth L1 veszteséggel, csak pozitív objektumokra. A labor a GlyphLab maskból rekonstruálja a metadata dobozait, és érintkező dobozokkal teszteli a fél-nyílt konvenciót.
A 26.2. Egy- és kétlépcsős detektor egység ezekre a fogalmakra építi az egy- és kétlépcsős detektorokat: a proposal, az objektumossági pontszám és az osztálylogit a dobozregressziós deltával együtt alkotja a detektálási veszteséget.