A Projekt III-ban a CNN-t új céllal használjuk: a GlyphLab-kép
osztálycímkéje helyett az alakzat térbeli kiterjedését kell megmondani.
A tanulási cél most nem a három orientációs osztály, hanem vagy az
előtér pixelcímkéje, vagy az azt befoglaló téglalap. A döntés első
lépése nem architekturális, hanem annotációs: mit tekintünk a modell
kimenetének, mi a hozzá tartozó ground truth, és milyen metrika méri a
teljesítményt. A GlyphLab két annotációt tartalmaz: a
masks.npy bináris előtér/háttér maszkot, a
metadata.csv pedig az előtér legkisebb befoglaló
téglalapját (bbox). Ebben az egységben e két cél közötti választást
alapozzuk meg, rögzítjük a target alakját, a csoportos splitet és az
üres eset konvencióját.
Előismeret: a 38.1. Adat, split és előzetes protokoll rögzítette a jelenetszintű splittel és a befagyasztott tesztprotokollt; a 27.1. Pixelszintű klasszifikáció és FCN bevezette a pixelszintű osztályozást és a per-pixel loss nevezőjét; a 26.4. Detektálási pipeline és hibaelemzés a detektálási pipeline-ban a doboztranszformációt; a 27.4. Instance mask és összetett feladat a semantic és instance maszk megkülönböztetését; a 35.1. Saliency és Grad-CAM a Grad-CAM-alapú lokalizációs vizualizációt. A Grad-CAM heurisztikus lokalizációt ad, de nem helyettesíti a tényleges maszk- vagy dobozcélú tanítást.
Induló kérdés. A GlyphLab-képeken az alakzat vékony vonal vagy rúd; a maszk gyakran csak néhány pixel széles. Elég-e a befoglaló téglalap ahhoz, hogy a „hol van az objektum” alkalmazási kérdést megválaszoljuk? A becslésünk: ha a felhasználás pixelmaszkot igényel, akkor nem, mert a bbox nem őrzi meg a maszk alakját, ürességét és több komponensét.
Legyen egy GlyphLab-kép
float32, NCHW tárolásban. A képhez két annotáció tartozik.
Semantic mask. A bináris szemantikus maszk minden pixelhez a háttér/előtér osztályt rendeli:
ahol
jelenti az előtér-,
a háttérpixelt. A sorindex
a
,
az oszlopindex
az
koordináta; mindkettő nullától indexelt. A GlyphLab
masks.npy uint8 típusú, de a tanítási target float32-re
konvertálható, mert a bináris BCEWithLogitsLoss float targetet vár. A
batch alak
Többosztályos általánosításban int64 target lenne, a modell pedig logitsot adna; a GlyphLab bináris előtere miatt itt a eset egyetlen logit-csatornával, BCEWithLogitsLoss-szal is leírható.
Bbox. A befoglaló téglalap négy egész koordináta:
a következő fél-nyílt intervallum-konvencióval:
A GlyphLab-szerződés ezt rögzíti: a doboz zérus alapú, fél-nyílt xyxy, és a bbox a maszk nemnulla pixeleinek legkisebb befoglaló téglalapja. Érvényes nemüres dobozra és . A cél batch alakja lokalizációs feladatban ; koordinátái pixel egységben értendők. A lokalizációs fej emellett általában egy objektum-jelenlét logitot is ad, hogy az üres képeket kezelni tudja.
Üres eset. Ha egy képen nincs egyetlen előtérpixel sem, a maszkcél a teljes nulla tömb , a dobozcél pedig a szentinel
A szentinel helyi, explicit sémadöntés, nem matematikai
szükségszerűség. Indoka kettős: (a) a negatív koordináta egyetlen
érvényes dobozban sem fordulhat elő, ezért az üres eset egyetlen
összehasonlítással felismerhető, és nem keverhető össze semmilyen valódi
dobozzal; (b) a dobozregressziós veszteségből az ilyen célokat kizárjuk,
így az érvénytelen állapot nem kerül a loss számlálójába. A
a fél-nyílt konvencióban nulla területű, érvénytelen doboz — nem egy
pixelt fed le (a
pixel doboza
)
—, tehát elvben szintén jelölhetne ürességet; a negatív szentinelt a
fenti két gyakorlati ok miatt választjuk. A 39.3.
Geometriai kontroll és metrika validate_box függvénye
és a 39.4. Alkalmazási riport és átadás exportja
ugyanezt a szentinelt fogadja el, és üres predikált maszkra ezt
írja.
Csoportos split. A maszk és a bbox a képhez tartozó
annotáció, ezért a splitet nem szabad képszinten újra véletlenezni. A
megfigyelési egység a scene_id: egy jelenet mindkét view-ja
és minden annotációja ugyanabba a train/val/test részbe kerül. A 38.1. Adat, split és előzetes protokoll már
levezette, hogy a jelenetszintű split a megnevezett használati
helyzetben torzítatlan tesztbecslőt ad, míg a képszintű véletlen split a
két view közötti hasonlóság miatt szivárgást okozna. A Project III ezt a
splitet nem változtatja meg: 120/30/30 jelenet, osztályrétegzetten
generálva.
Annotation convention. A kéziratban végig a nulla
alapú, sor-major pixelindexelést és a fél-nyílt [min,max)
intervallumot használjuk. A kép bal felső pixele a
cella; a
oszlop a
-edik
egységcellát fedi le, ezért a jobb szélső oszlopindex
.
A bbox a cellákat teljes egészében tartalmazza, nem a cellák közötti
élvonalat adja meg.
A két annotáció közötti átjárást két leképezéssel rögzítjük. Legyen az előtérpixelek halmaza.
Definíció (maszkból bbox, ). Ha , akkor
Ha , akkor .
Definíció (bboxból maszk, ). Érvényes esetén
A szentinel esetre .
Állítás (befoglaló téglalap konzisztenciája). A fenti definíciókkal:
Bizonyítás. (1) Véges nemüres halmazon a és létezik. A definícióból , tehát ; hasonlóan . A min/max tulajdonsága miatt tetszőleges -re , azaz , és , azaz .
Az (1) állítás szerint minden -beli cellában , a többi cellában . Egyenlőség pontosan akkor áll, ha a befoglaló téglalap minden cellája -ben van, tehát nincs benne háttérpixel.
Legyen érvényes. Ekkor nemüres, mert mindkét intervallum hossza legalább . A sor-minimum , a sor-maximum ; a szabály így -ot ad vissza. Az oszlopokra analóg módon -ot kapunk.
A szentinel definíciójából közvetlenül adódik.
A levezetés mutatja, hogy a fél-nyílt konvenció és a -es szabály együtt konzisztens: a bboxból visszaállított maszk befoglaló téglalapja pontosan az eredeti bbox, míg a maszkból származtatott bboxból visszaállított maszk felső becslése az eredeti maszknak. A kettő pontosan akkor esik egybe, ha a maszk maga is téglalap alakú. Ez a geometriai tény a célválasztás központi érve: a bbox cél csak téglalap-őrző, a maszk cél alak-őrző.
A választott fő annotáció. A Project III
alapváltozata a GlyphLab bináris foreground maszkját választja
szemantikus szegmentálási célként, mert (a) a masks.npy
teljes pixelcímkét ad, (b) a bbox abból egyértelműen származtatható,
fordítva nem, és (c) a maszkmetrika a vékony vonalak tényleges alakját
méri. A projekt végig ezen a főágon marad. A 39.3.
Geometriai kontroll és metrika és a 39.4.
Alkalmazási riport és átadás dobozai nem egy külön tanított
lokalizációs fej kimenetei, hanem a predikált maszkból a fenti
leképezéssel származtatott xyxy dobozok: a maszkot a
küszöb adja, üres predikált maszkra a doboz a
szentinel, és az exportot a 39.4. Alkalmazási riport
és átadás export_delivery.py szkriptje végzi. A maszkon
mért IoU neve mindenhol mask_iou, a dobozon mérté
bbox_iou. Önálló dobozregressziós fej tanítása a projektnek
nem része; legfeljebb transzferfeladatként szerepel.
Tekintsük az -ös maszkot:
0 0 0 0 0
0 1 1 0 0
0 1 0 1 0
0 0 1 0 0
0 0 0 0 0
Az előtérpixelek halmaza:
A definíció szerint
tehát a bbox . A befoglaló téglalap területe , míg a maszk területe . A bboxból visszaállított maszk:
0 0 0 0 0
0 1 1 1 0
0 1 1 1 0
0 1 1 1 0
0 0 0 0 0
A két maszk metszete pixel; a maszk-Dice:
a maszk-IoU pedig . Ha viszont a célt bboxban mérnénk, a predikált befoglaló téglalap pontosan megegyezik a ground truth bboxszal, tehát a bbox-IoU lenne. Ugyanaz a predikció a bbox-metrikában tökéletes, a maszk-metrikában gyenge; ez a későbbi tipikus tévedés alapja.
Most üres eset: legyen . Ekkor , és , tehát a körbejárás az üres maszkot adja vissza. A maszk-Dice-t az üres–üres esetre -nek definiáljuk; ha csak az egyik oldal üres, a Dice , mert a metszet nulla, a nevező pedig pozitív.
A labor egy specifikációs és konzisztencia-ellenőrző szkriptet készít. Nem tanít modellt: az a 39.2. Encoder–decoder vagy lokalizációs fej feladata. A labor célja, hogy a Project III target-szerződése géppel ellenőrzött legyen, és a későbbi tanítás ne indulhasson el ellentmondásos annotációval.
Munkakönyvtár és parancs. Hozzuk létre a
lab/project3 könyvtárat, mentsük a szkriptet
annotation_spec.py néven, majd futtassuk:
mkdir -p lab/project3
# a fenti kód lab/project3/annotation_spec.py néven mentendő
cd lab/project3
python annotation_spec.py --data ../dataA GlyphLab adatfájlok a lab/data könyvtárban vannak. A
környezet Python 3.10+, NumPy, nincs GPU, nincs külső súly. A seed itt
nem releváns, mert a szkript determinisztikus ellenőrzést végez; az
adatgenerátor seedjét a manifest.json rögzíti.
#!/usr/bin/env python3
# lab/project3/annotation_spec.py
"""Project III annotation specification and consistency check."""
import argparse
import csv
import json
from collections import defaultdict
from pathlib import Path
import numpy as np
H, W = 24, 24
EMPTY_BBOX = (-1, -1, -1, -1)
def mask_to_bbox(mask: np.ndarray) -> tuple[int, int, int, int]:
"""Binary mask (H, W) -> half-open xyxy bbox or EMPTY_BBOX."""
if not np.all(np.isin(mask, [0, 1])):
raise ValueError("mask values must be 0/1")
ys, xs = np.nonzero(mask)
if len(xs) == 0:
return EMPTY_BBOX
return int(xs.min()), int(ys.min()), int(xs.max()) + 1, int(ys.max()) + 1
def dice(y_true: np.ndarray, y_pred: np.ndarray) -> float:
"""Dice for two binary masks. Empty-empty convention: 1."""
yt = y_true.astype(np.float64)
yp = y_pred.astype(np.float64)
inter = float(np.sum(yt * yp))
denom = float(np.sum(yt) + np.sum(yp))
if denom == 0.0:
return 1.0
return 2.0 * inter / denom
def main() -> None:
parser = argparse.ArgumentParser()
parser.add_argument("--data", type=Path, default=Path("../data"))
parser.add_argument("--out", type=Path, default=Path("spec.json"))
args = parser.parse_args()
images = np.load(args.data / "images.npy")
masks = np.load(args.data / "masks.npy")
with open(args.data / "metadata.csv", newline="", encoding="utf-8") as f:
rows = list(csv.DictReader(f))
assert images.shape == (360, 1, H, W), images.shape
assert masks.shape == (360, 1, H, W), masks.shape
assert masks.dtype == np.uint8, masks.dtype
assert np.all(np.isin(masks, [0, 1])), "non-binary mask value"
mismatches = []
for r in rows:
i = int(r["index"])
b_file = (int(r["xmin"]), int(r["ymin"]),
int(r["xmax"]), int(r["ymax"]))
b_mask = mask_to_bbox(masks[i, 0])
if b_mask != b_file:
mismatches.append((i, b_file, b_mask))
by_scene = defaultdict(set)
for r in rows:
by_scene[r["scene_id"]].add(r["split"])
scene_conflicts = [s for s, sp in by_scene.items() if len(sp) > 1]
empty_count = sum(1 for i in range(len(masks)) if np.sum(masks[i]) == 0)
val_idx = [int(r["index"]) for r in rows if r["split"] == "val"]
all_foreground = np.ones((H, W), dtype=np.float64)
empty_pred = np.zeros((H, W), dtype=np.float64)
d_empty = [dice(masks[i, 0], empty_pred) for i in val_idx]
d_all = [dice(masks[i, 0], all_foreground) for i in val_idx]
spec = {
"target": "semantic_mask",
"input": {"shape": [1, H, W], "dtype": "float32", "range": [0.0, 1.0]},
"target_shape": [1, H, W],
"target_dtype": "float32",
"target_values": [0, 1],
"coordinate_convention":
"zero-indexed; y=row, x=column; bbox half-open [xmin,xmax) x [ymin,ymax)",
"empty_case": {
"mask": "all-zero array",
"bbox_sentinel": list(EMPTY_BBOX),
"dice_empty_empty": 1.0,
"dice_one_empty": 0.0,
},
"split": {
"unit": "scene_id",
"train_scenes": 120,
"val_scenes": 30,
"test_scenes": 30,
},
"baselines": {
"empty_mask": {"mean_val_dice": float(np.mean(d_empty))},
"all_foreground": {"mean_val_dice": float(np.mean(d_all))},
},
"consistency": {
"metadata_bbox_matches_mask": len(mismatches) == 0,
"mismatch_count": len(mismatches),
"empty_mask_count": empty_count,
"scene_split_conflicts": len(scene_conflicts),
},
}
with open(args.out, "w", encoding="utf-8") as f:
json.dump(spec, f, indent=2, ensure_ascii=False)
ok = len(mismatches) == 0 and len(scene_conflicts) == 0
print("CONSISTENCY_OK" if ok else "CONSISTENCY_FAIL")
print(json.dumps(spec, indent=2, ensure_ascii=False))
if __name__ == "__main__":
main()Átadandó eredmény. A labor kimenete a
lab/project3/spec.json, amely rögzíti a
semantic_mask targetet, a target shape-et, a koordináta- és
üreseset-konvenciót, a jelenetszintű splitet és a két baseline-t. A
konzol CONSISTENCY_OK sorának meg kell jelennie; ez azt
ellenőrzi, hogy a metadata.csv-beli bbox minden képre
pontosan megegyezik a maszkból származtatott befoglaló téglalappal, és
egyetlen jelenet sem került több splitbe. A
baselines.empty_mask.mean_val_dice várhatóan
,
ha minden val maszk nemüres; az all_foreground érték a val
maszkok átlagos kitöltöttségét tükrözi, és a későbbi modellnek ezt kell
jelentősen meghaladnia. Ezt az értéket a szkript a tényleges val
maszkokból számolja. Futási jegyzőkönyv (eredeti
GlyphLab-adat, NumPy 2.3.5): a konzol CONSISTENCY_OK-t írt,
a mismatch_count, az empty_mask_count és a
scene_split_conflicts egyaránt
,
az empty_mask baseline val-Dice értéke
,
az all_foreground baseline-é
;
ez utóbbi a kis előtérarányt tükrözi.
A baseline a val spliten mérhető, mert a val a modellválasztási halmaz; a végső, befagyasztott modell tesztkiértékelése a 39.4. Alkalmazási riport és átadás alfejezetben történik majd egyszer, a clean test maszkjain.
F1 (fogalmi, nehézség 1). Magyarázza el a szemantikus maszk, a bbox és az instance maszk különbségét. Adjon egy kis, -as bináris maszkpéldát, amelyben ugyanaz a szemantikus maszk két különböző instance-annotációt enged meg. Átadandó: legfeljebb féloldalas saját magyarázat és a konkrét példa.
F2 (levezetési, nehézség 2). Adott a -es maszk:
1 1 0 0
1 0 0 0
0 0 1 0
0 0 0 0
Számolja ki a bboxot és a kitöltött maszkot. Számolja ki a két maszk közötti Dice-t és IoU-t. Bizonyítsa a 3. szakasz állításának 2. pontját: pontonként, és adja meg, mikor áll egyenlőség. Átadandó: a bbox, a kitöltött maszk, a két metrikaérték és a bizonyítás lépései.
F3 (implementációs, nehézség 2). Írjon
mask_to_bbox és dice függvényt a fenti
konvencióval. Tesztelje három esetre: az 5. szakasz
-ös
példájára, az üres maszkra és az egyetlen
pixelt tartalmazó maszkra. Átadandó: futtatható kód és a három
kimenet.
F4 (hibakeresési, nehézség 2). Valaki a következő hibás függvényt írta:
def wrong_bbox(mask):
ys, xs = np.nonzero(mask)
return (xs.min(), ys.min(), xs.max(), ys.max())Magyarázza meg a hiba okát, mutassa meg egy olyan -es bemeneten, hogy a visszaadott bbox a fél-nyílt konvencióban nem tartalmazza az összes előtérpixelt, és adja meg a javítást. Mi a következménye a területre és az IoU-ra? Átadandó: hibalokalizáció, minimális reprodukció, javított kód és ellenőrzés.
F5 (kísérlettervezési transzfer, nehézség 3). Tervezzen egy GlyphLab-kísérletet, amely eldönti, hogy a választott alkalmazási kérdésre a maszkcél vagy a bboxcél illik jobban. Nevezze meg a kérdést, a baseline-t, a splitet, a metrikát és az érvényességi korlátot. Az előre megadott győztes nem kötelező; a negatív eredmény is elfogadható. Átadandó: egyoldalas protokollterv.
F1. A szemantikus maszk minden pixelhez osztálycímkét rendel; a bbox csak négy koordinátát ad; az instance maszk ezen felül az azonos osztályú objektumokat is elkülönülő példányokra bontja. Példa: a -as maszk
1 0 1
0 0 0
1 0 1
szemantikusan négy előtérpixelt tartalmaz, de instance-szinten lehet két függőleges, két vízszintes, vagy négy különálló folt felosztása; a szemantikus maszkból az instance-annotáció nem vezethető le. Ez a 27.4. Instance mask és összetett feladat tanulsága.
F2. A -es maszk előtere . A min/max:
tehát . A kitöltött maszk:
1 1 1 0
1 1 1 0
1 1 1 0
0 0 0 0
A metszet , a két terület és , tehát
A bizonyítás: a definíciójából minden -beli pixel koordinátái a és intervallumba esnek, ezért ott értéket vesz fel. A bboxon kívüli pixeleken , és , tehát minden cellában. Egyenlőség pontosan akkor, ha a bboxon belül minden cella szerint ; ez az az eset, amikor a maszk téglalapot tölt ki.
F3. A függvények a labor szkriptből vehetők. A tesztek:
import numpy as np
EMPTY = (-1, -1, -1, -1)
def mask_to_bbox(mask):
ys, xs = np.nonzero(mask)
if len(xs) == 0:
return EMPTY
return int(xs.min()), int(ys.min()), int(xs.max()) + 1, int(ys.max()) + 1
def dice(y_true, y_pred):
yt = y_true.astype(np.float64); yp = y_pred.astype(np.float64)
inter = float(np.sum(yt * yp)); denom = float(np.sum(yt) + np.sum(yp))
return 1.0 if denom == 0.0 else 2.0 * inter / denom
m1 = np.array([
[0,0,0,0,0],
[0,1,1,0,0],
[0,1,0,1,0],
[0,0,1,0,0],
[0,0,0,0,0]])
m2 = np.zeros((5,5), dtype=np.uint8)
m3 = np.zeros((5,5), dtype=np.uint8); m3[2,3] = 1
print(mask_to_bbox(m1), dice(m1, np.zeros_like(m1)))
print(mask_to_bbox(m2), dice(m2, np.zeros_like(m2)))
print(mask_to_bbox(m3), mask_to_bbox(np.zeros_like(m3)))Várt kimenet: , Dice a nulla predikcióval ; , Dice ; , üresre .
F4. A hiba oka: a max koordinátához nem
ad hozzá
-et,
így a fél-nyílt intervallum felső határa kihagyja a legnagyobb indexű
előtérpixelt. Példa:
esetén a hibás függvény
-t
ad, amely érvénytelen és nulla területű; a helyes eredmény
.
Ha a hibás dobozból kitöltő maszkot készítünk, az nem tartalmazza a
vagy
szélső pixelt, a metszet és az IoU torzul. A javítás:
def xyxy_bounds(xs, ys):
return (int(xs.min()), int(ys.min()),
int(xs.max()) + 1, int(ys.max()) + 1)és az üres eset kezelése EMPTY_BBOX visszaadással. Az
ellenőrzés a F3 három tesztjével történik.
F5. Egy lehetséges terv. Kérdés: „A GlyphLab vékony vonalainak térbeli azonosításához a pixelszintű maszk vagy a befoglaló bbox ad-e a felhasználási szerződésben jobb döntéshozatalt?” Baseline: üres maszk és teljes kép mint all-foreground; lokalizációs ágon a teljes képnyi fix bbox. Split: a 38.1. Adat, split és előzetes protokoll jelenetszintű, osztályrétegzett 120/30/30; modellválasztás csak clean val-on, teszt egyszer, befagyasztva. Metrika: a maszkágra kép-szintű binary Dice, üres–üres konvencióval; a bboxágra bbox-IoU. A két ág összehasonlításakor a bboxági predikciót -val maszkká alakítva is kiértékeljük Dice-on, de közöljük, hogy ez a kitöltési torzítás miatt konzervatív alsó becslés a bboxágra nézve. Érvényességi korlát: a GlyphLab szintetikus, egyobjektumos, zajos grayscale adat; az eredmény nem általánosítható többobjektumos vagy természetes képekre. Az intervallumokat jelenetszintű bootstrap adhatja [S02] szerint; a döntéshez a felhasználási következményt is rögzíteni kell, nem csak a pontszámot.
Tipikus tévedés. „A bboxra váltva a régi maszkmetrika automatikusan megfelelő marad.” Ez hamis. Legyen a ground truth maszk L-alak: -es kép, a felső sor és a bal oszlop , a többi ; területe . A ground truth bbox . Ha a modell a teljes befoglaló téglalapot adja, a bbox-IoU , de a maszk-Dice a valós L-maszk és a kitöltött téglalap között . A két target tehát más hibát definiál: ugyanaz az output az egyik metrikában tökéletes, a másikban gyenge. A metrikát a targettel együtt kell rögzíteni, nem a régi target után húzni.
Önellenőrzés. (1) Miért nem elég a bbox, ha a kérdés
a pixelmaszk? (2) Hogyan definiáltuk az üres bboxot és miért nem
?
(3) Mit jelent a fél-nyílt
a pixelcella-koordinátákban? (4) Miért scene_id a split
egysége? (5) Mikor egyenlő
és
?
Rövid válaszok. (1) Mert a bbox elveszti a maszk alakját, lyukjait és komponenseit. (2) A szentinel ; helyi sémadöntés, mert a negatív koordináta egyetlen érvényes dobozban sem fordul elő (könnyen felismerhető), és az ilyen célokat a dobozregressziós lossból kizárjuk. A nulla területű, érvénytelen doboz, nem egy pixelé. (3) A cellát indexeljük, és a felső határ nyílt, így a jobb alsó cella , indexig tart. (4) A két view közös jelenete függő megfigyelés; a képszintű split szivárgást okozna. (5) Pontosan akkor, ha a maszk téglalapot tölt ki.
Visszahívás. A 38.1. Adat, split és előzetes protokoll rögzítette a jelenetszintű osztályrétegzett splitet és a teszt egyszeri, befagyasztott használatát; a 27.1. Pixelszintű klasszifikáció és FCN a pixel-CE loss nevezőjét az érvényes pixelekre vezette le; a 35.1. Saliency és Grad-CAM Grad-CAM-vizualizációja heurisztikus lokalizáció, amely nem pótolja a tanított maszkcélt. A maszk itt rögzített bináris célja a 39.2. Encoder–decoder vagy lokalizációs fej alfejezetben a modellkimenet és a loss szerződésévé válik.
A Project III annotációs döntése a kérdéshez köti a célt. A szemantikus maszk minden pixelhez bináris előtér/háttér címkét rendel: batch alakban . A bbox négy fél-nyílt xyxy koordináta, a maszk legkisebb befoglaló téglalapja; üres célja , míg a maszk üres célja a nulla tömb. A lemma belátja, hogy a bboxból visszaállított maszk felső becslése az eredeti maszknak, és pontosan téglalapmaszkra egyeznek meg. A labor a metadata-bbox és a maszk konzisztenciáját ellenőrzi, baseline-ként üres és teljes előtér predikciót ad. A metrika target-specifikus: bbox-IoU és maszk-Dice nem felcserélhető.
A 39.2. Encoder–decoder vagy lokalizációs fej
az itt rögzített semantic_mask targetre építi és tanítja az
encoder–decoder szegmentáló hálót. A target shape, az üreseset-konvenció
és a jelenetszintű split ott válik a loss, a modellkimenet és a tanítási
ciklus szerződésévé.