5.20. Regressione e similarità¶
Altre due misurazioni sulla classe Image riassumono l’immagine come qualcosa di diverso da una distribuzione di valori dei pixel. La regressione lineare dei pixel soglia fornisce a un’applicazione una linea su cui agire – l’input classico per un robot inseguitore di linea. La misurazione della similarità fornisce a un’applicazione un singolo numero che descrive quanto due immagini si assomiglino – l’input naturale per un test di regressione su immagine di riferimento o per un rilevatore di cambiamenti grossolani.
5.20.1. Regressione lineare¶
Quando i pixel di primo piano di un’immagine formano per caso una linea attraverso il frame – il nastro su una pista che un robot sta seguendo, la linea dell’orizzonte, il bordo di una strada o di un corridoio – di solito l’applicazione non vuole ogni singolo pixel di primo piano. Vuole la linea di miglior adattamento che li attraversa tutti, parametrizzata in modo da poter decidere come è orientata la linea e dove attraversa il frame.
get_regression() esegue questo adattamento. Accetta la stessa forma di tupla di soglia usata da binary() e find_blobs(), identifica ogni pixel che corrisponde alla soglia e restituisce un singolo risultato line che descrive la linea di miglior adattamento attraverso quei pixel:
line = img.get_regression([(0, 60)])
if line:
img.draw_line((line.x1(), line.y1(),
line.x2(), line.y2()),
color=(255, 0, 0))
L’adattamento è una regressione lineare Theil-Sen, un metodo robusto che tollera i valori anomali meglio del più familiare adattamento ai minimi quadrati. Una piccola manciata di pixel lontani dalla linea reale non altera il risultato come farebbe con i minimi quadrati, il che corrisponde alla realtà di primo piano rumoroso di un output di soglia reale.
Il risultato line riporta gli estremi ritagliati al rettangolo dell’immagine (x1, y1, x2, y2), la lunghezza e la magnitudine della linea (length, magnitude) e la descrizione geometrica della linea in forma polare (theta, rho) – l’angolo della linea rispetto all’orizzontale e la sua distanza perpendicolare dall’origine. La forma polare è ciò che di solito vuole un anello di controllo: theta indica al robot in che direzione pende la linea, rho gli indica dove la linea attraversa l’immagine e un anello di retroazione sui due mantiene il robot centrato sulla linea.
Una manciata di argomenti chiave regola la robustezza e il costo. x_stride e y_stride saltano pixel durante l’adattamento – passi più grandi rendono la regressione più economica al costo di adattare meno pixel. area_threshold e pixels_threshold rifiutano le linee che non hanno abbastanza pixel corrispondenti dietro di sé. target_size riscala l’input a una dimensione inferiore prima dell’adattamento – la regressione viene eseguita più velocemente su un surrogato dell’immagine di 80 per 60 senza molta perdita nell’accuratezza della direzione della linea.
Se non è stato possibile adattare alcuna linea accettabile – se la soglia non ha corrisposto ad alcun pixel, o ha corrisposto a un pattern che non sembra una linea – il metodo restituisce None. Il codice di inseguimento di linea reale protegge ogni chiamata a get_regression() con un controllo None prima di accedere agli attributi della linea.
5.20.2. Similarità tra immagini¶
Un tipo diverso di misurazione: invece di chiedere «cosa contiene l’immagine?», chiede «quanto si assomigliano queste due immagini?». L’operazione a cui ricorrere è get_similarity(), che calcola lo Structural Similarity Index (SSIM) tra l’immagine sorgente e un’immagine di riferimento.
s = img.get_similarity(reference)
print(s.mean, s.stdev)
SSIM è la metrica standard di similarità tra immagini usata in tutta l’elaborazione delle immagini perché si comporta nel modo in cui si comporta l’intuizione umana sulla similarità – un piccolo spostamento o una piccola variazione di luminosità riduce leggermente il punteggio, mentre un grande cambiamento strutturale (oggetto mancante, scena diversa) lo riduce drasticamente. Il punteggio varia da -1 a +1: +1 significa che le due immagini sono identiche, 0 significa che non sono correlate e -1 significa che sono strutturalmente opposte. L’oggetto similarity restituito espone lo SSIM medio sull’immagine, oltre alla deviazione standard, al min e al max dei punteggi per tassello.
Per il tipo di confronto in cui un numero piccolo è migliore di uno grande – un test di regressione che dovrebbe riportare zero su «niente è cambiato» e crescere man mano che i cambiamenti si accumulano – il flag dssim=True restituisce la dissimilarità strutturale: lo SSIM medio sottratto da 1, in modo che il valore restituito sia 0.0 per immagini identiche e cresca man mano che differiscono.
5.20.3. Casi d’uso dello SSIM¶
Le due applicazioni comuni:
Test di regressione su immagine di riferimento. Un framework di test acquisisce un frame di riferimento in condizioni note come valide e lo memorizza come immagine di riferimento. Le esecuzioni successive del test acquisiscono nelle stesse condizioni e confrontano con l’immagine di riferimento usando SSIM. Un punteggio al di sopra di una certa soglia (0.95 o 0.98 a seconda della tolleranza) è un superamento; al di sotto è un fallimento. Il framework di test non ha bisogno di sapere cosa è cambiato – il punteggio SSIM è il segnale.
Rilevamento di cambiamenti grossolani. Un’applicazione che vuole una versione più grossolana della differenza tra frame – una che ignora le piccole variazioni di luminosità ma reagisce ai grandi cambiamenti strutturali – può usare SSIM rispetto a un frame di riferimento invece della difference() per pixel seguita da una soglia. SSIM è meno sensibile alla deriva dell’illuminazione rispetto alla differenza per pixel, il che lo rende la scelta migliore quando l’obiettivo è rilevare «la scena sembra sostanzialmente diversa» anziché «un singolo pixel qualsiasi è cambiato».
Entrambe le applicazioni usano la stessa chiamata – img.get_similarity(reference) – e si attivano su una soglia del punteggio restituito. La differenza sta solo nel fatto che la soglia sia alta (test di regressione, alla ricerca di una corrispondenza quasi identica) o bassa (rilevamento di cambiamenti, alla ricerca di un grande cambiamento strutturale qualsiasi).
5.20.4. La forma trasforma-e-confronta¶
Una sottigliezza utile: get_similarity() accetta gli stessi parametri x, y, x_scale, y_scale, roi, rgb_channel, alpha, color_palette, alpha_palette, hint e transform di draw_image(). L’immagine di riferimento viene posizionata, scalata e trasformata da quei parametri prima che venga eseguito il confronto SSIM.
Ciò significa che un’applicazione può chiedere «quanto è simile questa scena a un frame di riferimento dopo un noto spostamento / rotazione / scala» senza preparare un’immagine di riferimento già trasformata. È il modo economico per costruire un tracker che esplora uno spazio di parametri e riporta quale trasformazione del riferimento corrisponde meglio al frame corrente.