Come ruotare un array di bit

5

Almomentohoun PIL oggetto immagine che memorizzo come una matrice di bit (1 e 0). Tuttavia ora vorrei poter ruotare l'immagine di 45 gradi. Un modo per farlo è prendere l'immagine PIL originale, applicare una matrice di trasformazione su di essa, quindi convertirla in una matrice di bit. Il problema con questo approccio è che è computazionalmente costoso, soprattutto se voglio iniziare a fare più di una rotazione. Sarebbe più veloce modificare semplicemente l'array di bit direttamente.

Ho provato a utilizzare numpy.roll :

numpy.roll(bits, 45) # rotate 45 degrees

Sfortunatamente, questo fa solo uno spostamento circolare, non una rotazione angolare reale.

Quale algoritmo posso usare sull'array di bit per darmi l'output desiderato senza dover passare attraverso l'immagine originale? Anche se la mia applicazione è in Python, la tua risposta può essere in qualsiasi lingua ti trovi bene, sono più interessato all'algoritmo stesso non alla sintassi:)

    
posta paul smith 27.05.2013 - 21:33
fonte

4 risposte

4

Se vuoi sempre ruotare un'immagine di un angolo specifico ogni volta, devi solo eseguire una matematica pesante una volta (e in realtà non è così pesante). Il modo migliore per farlo è lavorare all'indietro. Per ogni pixel dell'immagine di destinazione, si calcola la posizione corrispondente nell'immagine di partenza. Questa coordinata di pixel "sorgente" viene salvata in quella che viene chiamata Tabella di ricerca o LUT. Una volta creato questo LUT per l'angolo e l'origine del luogo che si desidera, allora è molto veloce usare ogni voce del LUT per "spostare" i pixel di un'immagine sorgente sul pixel corretto dell'immagine di destinazione. Laddove questo diventa complicato e coinvolge più matematica, sta decidendo come pesare la data di origine per ottenere i dati di destinazione. Quando si lavora a ritroso dalle coordinate dell'immagine di destinazione intera, si finirà con coordinate a virgola mobile nell'immagine sorgente. Queste coordinate in virgola mobile devono essere interpolate. Il metodo più semplice consiste nell'utilizzare la coordinata di pixel interi "Vicina più vicina" ai valori in virgola mobile calcolati, ma ci sono altri algoritmi come "Bi-Linear" o "Bi-Cubic" che forniranno una migliore qualità dell'immagine finita ( ma sono ovviamente più lenti dei vicini più vicini "

    
risposta data 28.05.2013 - 02:41
fonte
3

Per vedere che non si tratta solo di spostare i punti, basta disegnare una cornice attorno all'immagine: nella versione ruotata, l'immagine avrà i bordi diagonali e quindi non si adatta nemmeno alle dimensioni del immagine originale.

Quindi, per ruotarlo dovrai calcolare dove ogni pixel va. Nota che il punto in alto a sinistra (0,1) non finirà a (1,1) ma in un punto della diagonale la cui distanza dall'origine è 1 : vale a dire, a (sqrt(2)/2, sqrt(2)/2) . Poiché sin(45) = cos(45) = sqrt(2)/2 , l'algoritmo che stai cercando è la moltiplicazione delle coordinate di ogni punto per questa matrice di trasformazione:

|  sqrt(2)/2  sqrt(2)/2 |
| -sqrt(2)/2  sqrt(2)/2 |

Guarda la pagina di Wikipedia su Matrici di trasformazione per i dettagli. Quindi, devi fare molte moltiplicazioni ma non devi calcolare qualsiasi seni o coseni (l'ho appena fatto per te dalla memoria). Puoi prendere altre scorciatoie, come suggerito dalle altre risposte, ma in un modo o nell'altro devi calcolare dove ogni pixel deve andare.

Ovviamente dovrai anche ritagliare o eseguire il pad per creare una normale immagine rettangolare.

PS. Meglio ancora, invece di implementare questa soluzione, affidarla a una libreria grafica che fa rotazioni. Oppure consulta questa domanda SO e la soluzione suggerita nei commenti sotto la domanda:

Consider scipy.ndimage.interpolation.shift() and rotate() or skimage.transform.fast_homography() for interpolated translations and rotations of 2D numpy arrays.

    
risposta data 02.06.2013 - 20:21
fonte
2

non c'è modo di fare la rotazione da angoli arbitrari senza seni e coseni, ma è possibile ottimizzare il calcolo a seconda di quali altri vincoli si è disposti ad imporre. Questo può diventare molto complicato, ma può comportare enormi miglioramenti per il "caso speciale" che hai definito.

Se le tue immagini sono tutte della stessa dimensione e ragionevolmente piccole, come la tua farfalla, e avevi intenzione di farne molte, potresti preformare il calcolo lento una volta, e semplicemente ricordare la x, y di ogni pixel del immagine sorgente che diventa la x ', y' dell'immagine di destinazione

    
risposta data 28.05.2013 - 01:55
fonte
0

Se si desidera limitare la rotazione a 45 gradi, non è necessario utilizzare sin e cos, in questo caso specifico si consiglia di utilizzare un algoritmo di disegno del diamante isometrico veloce e adattarlo alla matrice. Di solito un paio di cicli nidificati e 4 variabili (x, y, larghezza, altezza) lo faranno.

    
risposta data 20.10.2014 - 15:01
fonte

Leggi altre domande sui tag