2012-10-02 15 views
6

Non sono sicuro se esiste un nome per questo algoritmo che sto attualmente sviluppando - "algoritmo di quartiere in crescita" suona come un nome appropriato. Allora, qual è il mio problema?Algoritmo per disegnare un contorno o un tratto attorno a qualsiasi immagine trasparente alfa

Vorrei disegnare un tratto attorno a un'immagine trasparente alfa per delineare. La dimensione del tratto dovrebbe essere definibile dall'utente.

Ho un array che viene riempito da zero e uno, considera ogni elemento dell'array come una cella come in Game of Life. Un oggetto con 0 è vuoto (pixel trasparente), un oggetto con 1 è una cella di prima generazione (pixel non trasparente), il numero di generazioni è definito dalla dimensione del tratto circostante.

Questo esempio illustra una rettangolo circondato da valori di alfa:

0 0 0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 0 0 
0 0 0 1 1 1 1 0 0 0 
0 0 0 1 1 1 1 0 0 0 
0 0 0 1 1 1 1 0 0 0 
0 0 0 1 1 1 1 0 0 0 
0 0 0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 0 0 

Poi Vorrei lasciare quelle crescere una nuova generazione circondando ogni 0 generazione Moore prossimo. E 'la seconda generazione (corsa con 1px) - in tal modo la matrice si occupa in crescita come segue:

0 0 0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 0 0 
0 0 2 2 2 2 2 2 0 0 
0 0 2 1 1 1 1 2 0 0 
0 0 2 1 1 1 1 2 0 0 
0 0 2 1 1 1 1 2 0 0 
0 0 2 1 1 1 1 2 0 0 
0 0 2 2 2 2 2 2 0 0 
0 0 0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 0 0 

3a e 4a generazione (corsa con 3px):

4 4 4 4 4 4 4 4 4 4 
4 3 3 3 3 3 3 3 3 4 
4 3 2 2 2 2 2 2 3 4 
4 3 2 1 1 1 1 2 3 4 
4 3 2 1 1 1 1 2 3 4 
4 3 2 1 1 1 1 2 3 4 
4 3 2 1 1 1 1 2 3 4 
4 3 2 2 2 2 2 2 3 4 
4 3 3 3 3 3 3 3 3 4 
4 4 4 4 4 4 4 4 4 4 

Fin qui tutto bene. Sto realizzare questo compito semplice dal seguente frammento di codice:

for (int gen = 1; gen <= 4; gen++) 
{ 
    for (int x = 1; x < arrayWidth - 1; x++) 
    { 
     for (int y = 1; y < arrayHeight - 1; y++) 
     { 
      // See if this cell is in the current generation. 
      if (_generation[x + arrayWidth * y] == gen) 
      { 
       // Generate next generation. 
       for (int i = x - 1; i <= x + 1; i++) 
       { 
        for (int j = y - 1; j <= y + 1; j++) 
        { 
         if (_generation[i + arrayWidth * j] == 0 || _generation[i + arrayWidth * j] > gen) 
         { 
          _generation[i + arrayWidth * j] = gen + 1; 
         } 
        } 
       } 
      } 
     } 
    } 
} 

Questo approccio funziona perfettamente per le forme semplici come un rettangolo, per esempio. Ma come posso fare questo per un'ellisse? Non appena abbiamo una specie di modello di scala nelle cellule, sto ottenendo risultati disordinato:

0 0 0 0 0 0 0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 0 0 0 0 0 0 
0 0 0 0 0 1 1 1 1 0 0 0 0 0 
0 0 0 0 1 1 1 1 1 1 0 0 0 0 
0 0 0 1 1 1 1 1 1 1 1 0 0 0 
0 0 1 1 1 1 1 1 1 1 1 1 0 0 
0 0 1 1 1 1 1 1 1 1 1 1 0 0 
0 0 1 1 1 1 1 1 1 1 1 1 0 0 
0 0 1 1 1 1 1 1 1 1 1 1 0 0 
0 0 1 1 1 1 1 1 1 1 1 1 0 0 
0 0 0 1 1 1 1 1 1 1 1 0 0 0 
0 0 0 0 1 1 1 1 1 1 0 0 0 0 
0 0 0 0 0 1 1 1 1 0 0 0 0 0 
0 0 0 0 0 0 0 0 0 0 0 0 0 0 
0 0 0 0 0 0 0 0 0 0 0 0 0 0 

0 0 0 0 0 0 0 0 0 0 0 0 0 0 
0 0 0 0 2 2 2 2 2 2 0 0 0 0 
0 0 0 2 2 1 1 1 1 2 2 0 0 0 
0 0 2 2 1 1 1 1 1 1 2 2 0 0 
0 2 2 1 1 1 1 1 1 1 1 2 2 0 
0 2 1 1 1 1 1 1 1 1 1 1 2 0 
0 2 1 1 1 1 1 1 1 1 1 1 2 0 
0 2 1 1 1 1 1 1 1 1 1 1 2 0 
0 2 1 1 1 1 1 1 1 1 1 1 2 0 
0 2 1 1 1 1 1 1 1 1 1 1 2 0 
0 2 2 1 1 1 1 1 1 1 1 2 0 0 
0 0 2 2 1 1 1 1 1 1 2 2 0 0 
0 0 0 2 2 1 1 1 1 2 2 0 0 0 
0 0 0 0 2 2 2 2 2 2 0 0 0 0 
0 0 0 0 0 0 0 0 0 0 0 0 0 0 

0 0 0 3 3 3 3 3 3 3 3 0 0 0 
0 0 3 3 2 2 2 2 2 2 3 3 0 0 
0 3 3 2 2 1 1 1 1 2 2 3 3 0 
3 3 2 2 1 1 1 1 1 1 2 2 3 3 
3 2 2 1 1 1 1 1 1 1 1 2 2 3 
3 2 1 1 1 1 1 1 1 1 1 1 2 3 
3 2 1 1 1 1 1 1 1 1 1 1 2 3 
3 2 1 1 1 1 1 1 1 1 1 1 2 3 
3 2 1 1 1 1 1 1 1 1 1 1 2 3 
3 2 1 1 1 1 1 1 1 1 1 1 2 3 
3 2 2 1 1 1 1 1 1 1 1 2 2 3 
3 3 2 2 1 1 1 1 1 1 2 2 3 3 
0 3 3 2 2 1 1 1 1 2 2 3 3 0 
0 0 3 3 2 2 2 2 2 2 3 3 0 0 
0 0 0 3 3 3 3 3 3 3 3 0 0 0 

Se si applica questo algoritmo per un'ellisse, il contorno sguardi un po 'strano, perché di questo problema (a sinistra: risultato algoritmo , a destra: risultato richiesto):

Il problema qui è che non voglio avere quei 2 2 e 3 3 blocchi duplicati che si verificano ogni volta che ho questa "scala" modello:

1 0 0 0 0 0 0 1 
0 1 0 0 0 0 1 0 
0 0 1 0 0 1 0 0 
0 0 0 1 1 0 0 0 

Voglio che i calcoli di cui sopra generazione 2a e 3a simile a questa:

0 0 0 0 0 0 0 0 0 0 0 0 0 0 
0 0 0 0 0 2 2 2 2 0 0 0 0 0 
0 0 0 0 2 1 1 1 1 2 0 0 0 0 
0 0 0 2 1 1 1 1 1 1 2 0 0 0 
0 0 2 1 1 1 1 1 1 1 1 2 0 0 
0 2 1 1 1 1 1 1 1 1 1 1 2 0 
0 2 1 1 1 1 1 1 1 1 1 1 2 0 
0 2 1 1 1 1 1 1 1 1 1 1 2 0 
0 2 1 1 1 1 1 1 1 1 1 1 2 0 
0 2 1 1 1 1 1 1 1 1 1 1 2 0 
0 0 2 1 1 1 1 1 1 1 1 2 0 0 
0 0 0 2 1 1 1 1 1 1 2 0 0 0 
0 0 0 0 2 1 1 1 1 2 0 0 0 0 
0 0 0 0 0 2 2 2 2 0 0 0 0 0 
0 0 0 0 0 0 0 0 0 0 0 0 0 0 

0 0 0 0 0 3 3 3 3 0 0 0 0 0 
0 0 0 0 3 2 2 2 2 2 3 0 0 0 
0 0 0 3 2 1 1 1 1 2 3 0 0 0 
0 0 3 2 1 1 1 1 1 1 2 3 0 0 
0 3 2 1 1 1 1 1 1 1 1 2 3 0 
3 2 1 1 1 1 1 1 1 1 1 1 2 3 
3 2 1 1 1 1 1 1 1 1 1 1 2 3 
3 2 1 1 1 1 1 1 1 1 1 1 2 3 
3 2 1 1 1 1 1 1 1 1 1 1 2 3 
3 2 1 1 1 1 1 1 1 1 1 1 2 3 
0 3 2 1 1 1 1 1 1 1 1 2 3 0 
0 0 3 2 1 1 1 1 1 1 2 3 0 0 
0 0 0 3 2 1 1 1 1 2 3 0 0 0 
0 0 0 3 2 2 2 2 2 2 3 0 0 0 
0 0 0 0 3 3 3 3 3 3 0 0 0 0 

Ho provato numerosi metodi per filtrare i blocchi di celle duplicati, ma non riesco a trovare una soluzione facile e generico per risolvere il problema.

Qualche idea su come ottenere tratti/tratti come quelli che ottengo da Photoshop o Paint.NET?

Grazie!

Acclamazioni P

+2

Penso che si potrebbe fare progressi da 'dilation' morfologica con un appropriato' strutturazione element'. Non ho tempo di spiegare in dettaglio, mentre aspetti una risposta, inizia a leggere su http://en.wikipedia.org/wiki/Mathematical_morphology –

+1

La tua domanda dovrebbe essere un esempio per tutti - "Come chiedere una buona domande " –

risposta

5

Il nome proprio è dilation, controlla le operazioni morfologiche. Dovresti provare la dilatazione con l'elemento cerchio, questo ti darà il risultato richiesto.

Ecco un codice Matlab che mostra come è fatto:

im = imcircle(70); 
im = padarray(im,[20,20]); 
figure;imshow(im); 
im2 = imdilate(im,strel('disk',8)); 
figure;imshow(im2); 

enter image description here

+2

Questo è esattamente quello che sto cercando! Grazie! Conoscere il nome di questo algoritmo rende la ricerca molto più semplice ...;) Alcuni link molto utili: http://homepages.inf.ed.ac.uk/rbf/HIPR2/dilate.htm Anche il riferimento Matlab per la scelta un kernel appropriato: http://www.mathworks.de/de/help/images/ref/strel.html – barnacleboy

+1

Questo concetto mi ha aiutato a ridurre uno script di 160+ linee, complesso fino a ~ 20 linee di facile lettura. Google mi ha portato a questa grande pagina: https://docs.opencv.org/3.0-beta/doc/py_tutorials/py_imgproc/py_morphological_ops/py_morphological_ops.html – itnAAnti

Problemi correlati