5.23. Correzione della prospettiva¶
Avvertimento
La matrice transform 3 per 3 arbitraria è supportata solo sulla OpenMV Cam N6 – la parola chiave viene ignorata silenziosamente su ogni altra scheda. Le applicazioni che devono funzionare altrove devono usare il metodo predefinito rotation_corr() (con la sua forma corners=) oppure pre-calcolare l’immagine corretta fuori dalla scheda.
Il metodo predefinito rotation_corr() racchiude una particolare famiglia di deformazioni prospettiche dietro un piccolo insieme di parametri, e funziona su ogni scheda supportata. Alcune applicazioni necessitano di una deformazione che non rientra in quella forma: una rimappatura proiettiva arbitraria da un quadrilatero a un altro, una correzione calibrata per un montaggio noto già elaborata off-line, una matrice di deformazione fornita già pronta da qualche algoritmo a monte. Per questi casi, draw_image() – insieme a copy(), crop() e scale() – accetta una parola chiave transform che prende una matrice 3 per 3 costruita a mano che descrive direttamente la deformazione.
5.23.1. Trasformazioni affini e proiettive¶
Le deformazioni geometriche sono espresse in coordinate omogenee: la posizione del pixel (x, y) con un 1 aggiunto, moltiplicata per una matrice 3 per 3.
La forma affine è il punto di partenza. La sua riga inferiore è fissata a \((0, 0, 1)\):
Scritta per esteso, ogni coordinata di output è una combinazione lineare delle coordinate di input più una costante:
che copre il ridimensionamento, la rotazione, lo shearing e la traslazione in qualsiasi combinazione – e sotto tutte queste, le linee parallele restano parallele.
La forma proiettiva (prospettica) libera la riga inferiore:
Scritta per esteso:
La divisione per \(w' = g x + h y + 1\) è ciò che rende la trasformazione proiettiva anziché meramente affine. Quando \(g\) e \(h\) sono entrambi zero, \(w'\) resta a uno e la divisione non fa nulla – di nuovo la forma affine. Quando uno dei due è non nullo, \(w'\) varia con la posizione di input e i pixel in posizioni diverse vengono scorciati di quantità diverse, il che non mantiene più le linee parallele parallele – è esattamente l’effetto keystone di guardare un piano piatto da un angolo obliquo. Una trasformazione proiettiva è la deformazione geometrica più generale che porta le linee rette in linee rette; il ridimensionamento, il ribaltamento, la trasposizione, la rotazione e la correzione della rotazione a quattro angoli sono tutti casi speciali di una sola.
Le trasformazioni con nome derivano direttamente dalla forma affine. La trasformazione identità è la matrice identità, e:
Per la maggior parte delle trasformazioni costruite a mano un’applicazione parte da una di queste come base e moltiplica ulteriori matrici per ogni operazione aggiuntiva, terminando con una singola matrice 3 per 3 che descrive la deformazione composita. Le matrici si applicano da destra a sinistra: \(M = T R S\) esegue prima il ridimensionamento, poi la rotazione, poi la traslazione. La composizione di cui tutti hanno bisogno prima o poi è la rotazione attorno al centro dell’immagine – una matrice di rotazione nuda fa ruotare l’immagine attorno all’origine dei pixel nell’angolo in alto a sinistra, quindi la versione centrata sposta il centro \((c_x, c_y)\) all’origine, ruota e lo riporta indietro:
5.23.2. La parola chiave transform¶
La matrice viene fornita tramite una parola chiave transform, passata come ulab.numpy.ndarray 3 per 3. Il metodo a cui ricorrere è draw_image(), che deforma la sorgente attraverso la matrice mentre la disegna su una destinazione – il risultato finisce in un buffer controllato dall’applicazione, e la deformazione si compone con tutto il resto nella chiamata: il ridimensionamento, la fusione alpha, il mascheramento.
import ulab.numpy as np
M = np.array([[1.2, 0.0, -20.0],
[0.0, 1.2, -15.0],
[0.0, 0.0, 1.0]])
canvas.draw_image(img, transform=M)
L’esempio deforma img su canvas ridimensionata di 1,2 in ciascuna direzione e spostata a sinistra e verso l’alto rispettivamente di 20 e 15 pixel – una deformazione affine costruita direttamente dagli elementi della matrice descritti sopra. La stessa parola chiave su copy(), crop() e scale() applica la deformazione all’immagine stessa.