7.7. Normalization¶
ml.Model.predict() accetta un elenco di input perché alcune reti hanno più di un tensore di input, ma l’elenco non ha modo di trasportare argomenti per-input inline – non c’è uno slot per argomenti con nome per «ritaglia questo input su (x, y, w, h) ma lascia gli altri input invariati». ml.preprocessing.Normalization è il wrapper che colma questa lacuna. Un’istanza di Normalization contiene i parametri per un input; lo script passa l’input incapsulato nell’elenco di predict ogni volta che ha bisogno di qualcosa di diverso dai valori predefiniti.
La ragione più comune per ricorrervi è ritagliare una regione specifica del frame catturato da passare alla rete invece dell’intera immagine.
7.7.1. Parametri¶
Normalization(scale=(0.0, 1.0),
mean=(0.0, 0.0, 0.0),
stdev=(1.0, 1.0, 1.0),
roi=None)
roi– rettangolo(x, y, w, h)nel frame sorgente da ritagliare prima del ridimensionamento. Il valore predefinito è l’intero frame. La maggior parte degli usi diNormalizationimposta solo questo parametro.scale– l’intervallo(min, max)che i tensori di input in virgola mobile si aspettano dopo la normalizzazione. L’intervallo dei pixel0..255viene mappato linearmente in questo intervallo. I valori comuni sono(0.0, 1.0)per le reti addestrate con ReLU e(-1.0, 1.0)per le reti normalizzate simmetricamente.mean– media per canale(R, G, B)sottratta dall’immagine dopo il ridimensionamento. Corrisponde alle statistiche di canale contro cui la rete è stata addestrata –(0.485, 0.456, 0.406)per le reti derivate da ImageNet è l’esempio canonico. Le reti in scala di grigi riducono la media a un valore di luma usando lo standard0.299*R + 0.587*G + 0.114*B.stdev– deviazione standard per canale(R, G, B)per cui l’immagine viene divisa dopo che la media è stata sottratta, sempre in corrispondenza delle statistiche di addestramento della rete. Ridotta a luma nello stesso modo per le reti in scala di grigi.
7.7.2. Quando i parametri contano¶
scale, mean e stdev vengono ignorati quando il input_dtype della rete è int8 o uint8. Per le reti con input intero i byte dell’immagine ritagliata vengono scritti direttamente nel tensore e il input_scale e il input_zero_point della rete stessa gestiscono la conversione da intero a reale. I tre parametri contano solo quando la rete si aspetta input in virgola mobile.
roi viene letto in ogni caso – controlla quale parte del frame sorgente raggiunge la rete indipendentemente dal dtype di input.
7.7.3. ROI e ridimensionamento¶
La ROI viene scalata bilinearmente dalle sue dimensioni sorgente alle dimensioni di input della rete. L’immagine viene centrata nella destinazione e il ridimensionamento riempie la destinazione – non preserva le proporzioni. Una ROI non quadrata fornita a un input di rete quadrato risulta allungata orizzontalmente o verticalmente.
Se l’allungamento conti o meno dipende dalla rete. I modelli di rilevamento volti e di landmark come la famiglia MediaPipe (BlazeFace, FaceLandmarks, HandLandmarks, MoveNet) sono stati addestrati su ritagli quadrati e degradano rapidamente quando le proporzioni dell’input non sono corrette; per questi, l’applicazione deve fornire loro una ROI quadrata – catturando a una framesize quadrata tramite window() oppure ritagliando con il parametro roi=. I rilevatori di oggetti della famiglia YOLO sono in genere addestrati con augmentation che include allungamenti casuali e accettano ROI non quadrate senza grande perdita di accuratezza; passare direttamente l’intero frame catturato di solito va bene.
Quando le dimensioni di input della rete corrispondono esattamente alla ROI, il ridimensionamento si riduce a una copia, che è il caso più economico.
7.7.4. Sovrascrittura del valore predefinito¶
predict() incapsula automaticamente ogni input image.Image con Normalization() – i parametri predefiniti descritti sopra. La maggior parte dei modelli forniti con la camera è stata addestrata su intervalli di pixel già coperti dai valori predefiniti, quindi il caso comune è passare l’immagine direttamente:
result = model.predict([img])
Per usare una ROI personalizzata – la sovrascrittura più comune – costruisci un Normalization con la ROI impostata e associa l’immagine ad esso:
from ml.preprocessing import Normalization
norm = Normalization(roi=(80, 60, 160, 120))
result = model.predict([norm(img)])
Per corrispondere alle statistiche di canale al tempo dell’addestramento di una rete, imposta i parametri in virgola mobile:
norm = Normalization(scale=(0.0, 1.0),
mean=(0.485, 0.456, 0.406),
stdev=(0.229, 0.224, 0.225))
result = model.predict([norm(img)])
Chiamare l’istanza di Normalization sull’immagine restituisce una nuova istanza associata da cui il motore riempie il tensore. L’istanza associata è ciò che predict accetta al posto dell’immagine grezza e, poiché è un oggetto per-input, una rete multi-input può combinare immagini con ROI diverse nello stesso elenco di predict.
Per le reti che si aspettano input che l’applicazione ha già prodotto in forma di tensore – un buffer proveniente da una periferica, un ndarray calcolato da un’altra pipeline, dati numerici non di immagine – salta interamente Normalization e passa l’ndarray o un oggetto invocabile che lo produce. predict() li passa al motore senza incapsularli.