2011-09-16 7 views
7

Sto leggendo DIP 2a edizione da Gonzalez e Woods e provo a sporcarmi le mani con la maschera laplaciana (pagina 129 & 130) usando wxImage.implementare laplacian 3x3

float kernel [3][3]= {{1, 1, 1},{1,-8, 1},{1, 1, 1}}; 

Ecco l'elaborazione loop:

unsigned char r,g,b;      

float rtotal, gtotal, btotal; rtotal = gtotal = btotal = 0.0; 
//ignore the border pixel    

for(int i = 1; i<imgWidth-1; i++) 
{ 

    for(int j = 1; j<imgHeight-1; j++) 
    { 

    rtotal = gtotal=btotal =0.0; 


     for(int y = -1; y<=1;y++) 

     { 

      for(int x = -1; x<=1;x++) 

      { 

      // get each channel pixel value 

      r = Image->GetRed(i+y,j+x); 

      g = Image->GetGreen(i+y,j+x); 

      b = Image->GetBlue(i+y,j+x); 

      // calculate each channel surrouding neighbour pixel value base 

      rtotal += r* kernel[y+1][x+1]; 

      gtotal += g* kernel[y+1][x+1] ; 

      btotal += b* kernel[y+1][x+1]; 

      } 

    } 
      //edit1: here is how to sharpen the image 
      // original pixel - (0.2 * the sum of pixel neighbour) 
      rtotal = loadedImage->GetRed(x,y) - 0.2*rtotal; 

    gtotal = loadedImage->GetGreen(x,y) - 0.2*gtotal; 

    btotal = loadedImage->GetBlue(x,y) - 0.2*btotal; 
    // range checking 

    if (rtotal >255) rtotal = 255; 

     else if (rtotal <0) rtotal = 0; 

    if(btotal>255) btotal = 255; 

     else if(btotal < 0) btotal = 0; 

    if(gtotal > 255) gtotal = 255; 

     else if (gtotal < 0) gtotal =0; 

    // commit new pixel value 

    Image->SetRGB(i,j, rtotal, gtotal, btotal); 

ho applicato che al quadro Polo Nord (immagine grigio) e tutto quello che ottiene è un blob di pixel bianchi e neri!

Qualche idea in cui potrei aver perso qualcosa nei cicli for?

Edit1: Finalmente ottenere la risposta dopo guardarsi intorno su google. Questa roba da dsp è decisamente difficile! Ho aggiunto al codice sopra, renderà più nitida l'immagine.

Acclamazioni

+0

Questa sarebbe una buona domanda per dsp.stackexchange.com – Dima

risposta

5

In primo luogo, il risultato della convoluzione con un laplaciano può avere valori negativi. Considera un pixel con un valore di 1 circondato da 0. Il risultato della convoluzione a quel pixel sarà -8.

In secondo luogo, l'intervallo del risultato sarà compreso tra [-8 * 255, 8 * 255], che sicuramente non si adatta a 8 bit. Essenzialmente, quando esegui il controllo dell'intervallo, perdi la maggior parte delle informazioni e la maggior parte dei pixel risultanti finirà per essere 0 o 255.

Quello che devi fare è archiviare il risultato in un array di digitare che è firmato e abbastanza largo da gestire l'intervallo. Quindi, se si desidera produrre un'immagine a 8 bit, è necessario ridimensionare i valori in modo che -8 * 255 esegua il mapping su 0 e 8 * 255 esegua il mapping su 255. Oppure è possibile ridimensionarlo in modo che le mappe del valore minimo corrispondano a 0 e il più grande valore mappe a 255.

Edit: in questo caso specifico, è possibile effettuare le seguenti operazioni:

rtotal = (rtotal + 8 * 255)/(16 * 255) * 255; 

che semplifica al

rtotal = (rtotal + 8 * 255)/16; 

questo sarebbe mappare rtotal in una gamma tra 0 e 255 senza troncamento. Si dovrebbe fare lo stesso per gtotal e btotal.

+0

Grazie per la risposta. Ma quello che non capisco è che quando eseguo il calcolo vicino, lo memorizzo in r/g/btotal che è un valore float dovrebbe essere abbastanza grande, giusto? Per quanto posso vedere, il valore massimo di un vicino può essere 8 * 255 o -8 * 255 come hai detto sopra che è (-) 2040 * 9 (nove vicini tutti insieme) = (-) 18360. Guardo intervallo float in C++ e dice che l'intervallo di float è di 7 cifre. Tuttavia, ora capisco perfettamente perché ho un grande blog di pixel bianchi e neri perché ho perso altri calcoli. Vedi la mia edizione OP. Grazie! – bili

+0

Il fatto che si sta utilizzando un float per r/g/btotal va bene. Il problema si verifica quando si tronca il valore di r/g/btotal tra 0 e 255. Invece di impostare tutto sotto 0 a 0 e tutto sopra 255 a 255 si dovrebbe ridimensionare il valore. Stai troncando l'intervallo, mentre dovresti comprimere l'intervallo. – Dima

+0

Sì, ho capito ora. Dovrei ridimensionare il valore invece di troncarlo. tyvm! – bili

1

Non sei dovrebbero dividere per il numero di pixel nella maschera dopo aver calcolato la somma pesata, producendo così una media ponderata? Senza questo, la somma di nove valori di pixel (anche quando moltiplicati con valori di maschera non troppo luminosi) supererà facilmente 255.

+2

La somma dei valori nella matrice maschera è zero, quindi no, non ci sarà alcun guadagno complessivo che causerebbe un overflow.È necessario fare attenzione ad usare un tipo più grande nei calcoli intermedi, tuttavia, altrimenti si potrebbe sovrasfruttare un valore a 8 bit mentre si calcola la somma. Per ogni pixel, il laplaciano lo sostituisce con la somma di tutti i suoi vicini meno otto volte il valore originale del pixel, qualcosa di un'operazione di differenziazione. Viene utilizzato nel rilevamento dei bordi. –

+0

Grazie. Lo esaminerò ora. – bili

+0

@Jason R: Fai una risposta - Penso che sia esattamente quello che è successo qui. –

2

Penso che il tuo problema è che r, geeb sono di tipo unsigned int e che, a seconda su quale compilatore stai usando e su come si sta ottimizzando, stai implicitamente proiettandoli su float nelle linee rtotal += r* kernel[y+1][x+1]; ecc. Ma se il compilatore si adatta in modo diverso alle tue aspettative, il calcolo del valore medio non funzionerà perché int unsigned non può essere negativo .

Soluzione: modificare r, geb per flottare.

Non farà alcuna differenza, ma c'è un piccolo errore nelle linee r = Image->GetRed(i+y,j+x); perché I è in loop sull'orizzontale e j è in loop in verticale.

+0

Quando si moltiplica un float con un char senza segno, il compilatore promuoverà sempre il char senza segno su un float. Ma non si adattano a 8 bit alla fine e i valori negativi sono sicuramente il problema. – Dima

+0

il motivo r, g, b sono caratteri non firmati perché le funzioni GetRed/Green/Blue restituiscono caratteri non firmati. – bili

Problemi correlati