2015-04-07 11 views
7

Attualmente sto lavorando all'implementazione di un algoritmo di soglia chiamato Bradley Adaptive Thresholding.Algoritmo di soglia adattativo Bradley

Ho seguito principalmente due collegamenti per capire come implementare questo algoritmo. Sono anche riuscito a implementare con successo altri due algoritmi di soglia, principalmente Otsu's Method e Balanced Histogram Thresholding.

Ecco i due collegamenti che ho seguito per creare l'algoritmo Bradley Adaptive Thresholding.

http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.420.7883&rep=rep1&type=pdf

Bradley Adaptive Thresholding Github Example

Ecco la sezione del mio codice sorgente in Python dove sto facendo funzionare l'algoritmo e salvare l'immagine. Io uso lo Python Imaging Library e nessun altro strumento per realizzare ciò che voglio fare.

def get_bradley_binary(inp_im): 
    w, h = inp_im.size 
    s, t = (w/8, 0.15) 

    int_im = Image.new('L', (w, h)) 
    out_im = Image.new('L', (w, h)) 

    for i in range(w): 
     summ = 0 
     for j in range(h): 
      index = j * w + i 

      summ += get_pixel_offs(inp_im, index) 

      if i == 0: 
       set_pixel_offs(int_im, index, summ) 
      else: 
       temp = get_pixel_offs(int_im, index - 1) + summ 
       set_pixel_offs(int_im, index, temp) 

    for i in range(w): 
     for j in range(h): 
      index = j * w + i 

      x1,x2,y1,y2 = (i-s/2, i+s/2, j-s/2, j+s/2) 

      x1 = 0 if x1 < 0 else x1 
      x2 = w - 1 if x2 >= w else x2 
      y1 = 0 if y1 < 0 else y1 
      y2 = h - 1 if y2 >= h else y2 

      count = (x2 - x1) * (y2 - y1) 

      a1 = get_pixel_offs(int_im, y2 * w + x2) 
      a2 = get_pixel_offs(int_im, y1 * w + x2) 
      a3 = get_pixel_offs(int_im, y2 * w + x1) 
      a4 = get_pixel_offs(int_im, y1 * w + x1) 

      summ = a1 - a2 - a3 + a4 

      temp = get_pixel_offs(inp_im, index) 
      if temp * count < summ * (1.0 - t): 
       set_pixel_offs(out_im, index, 0) 
      else: 
       set_pixel_offs(out_im, index, 255) 

    return out_im 

Qui è la sezione del mio codice che illustra l'implementazione di queste serie e ottenere metodi che non avete mai visto prima.

def get_offs(image, x, y): 
    return y * image.size[0] + x 

def get_xy(image, offs): 
    return (offs % image.size[0], int(offs/image.size[0])) 

def set_pixel_xy(image, x, y, data): 
    image.load()[x, y] = data 

def set_pixel_offs(image, offs, data): 
    x, y = get_xy(image, offs) 
    image.load()[x, y] = data 

def get_pixel_offs(image, offs): 
    return image.getdata()[offs] 

def get_pixel_xy(image, x, y): 
    return image.getdata()[get_offs(image, x, y)] 

Infine, ecco le immagini di input e di output. Queste sono le stesse immagini utilizzate nella ricerca originale nel primo collegamento che ti ho fornito. Nota: l'immagine di output è quasi completamente bianca e potrebbe essere difficile da vedere, ma l'ho comunque fornita nel caso in cui qualcuno volesse davvero averlo come riferimento.

Input Image Output Image

+1

ciò che non funziona, la corretta generazione di immagine di output? Hai qualche test non visivo? – Ashalynd

+0

Sì, la corretta generazione di immagini in uscita non funziona, ho usato la stessa identica immagine che il documento di ricerca utilizza per il test e l'immagine di output è completamente bianca e non assomiglia a nulla di ciò che fa l'immagine di output del documento di ricerca.Per quanto riguarda i test non visivi, non sono sicuro di cosa intendi. –

risposta

8

Non è possibile creare l'immagine integrale con PIL il modo in cui si sta facendo perché l'immagine che si sono imballaggio dati in non può accettare valori superiori a 255. I valori della immagine integrale ottenere molto grande perché sono le somme dei pixel sopra e a sinistra (vedi pagina 3 del tuo white paper). Cresceranno molto più grandi di 255, quindi hai bisogno di 32 bit per pixel per memorizzarli.

È possibile verificare ciò creando un'immagine PIL in modalità "L" e quindi impostando un pixel su 1000000 o un numero elevato. Poi, quando si legge di nuovo il valore, esso ritornerà 255.

>>> from PIL import Image 
>>> img = Image.new('L', (100,100)) 
>>> img.putpixel((0,0), 100000) 
>>> print list(img.getdata())[0] 
255 

EDIT: Dopo aver letto la documentazione PIL, si può essere in grado di utilizzare PIL se si crea l'immagine integrale in modalità "io" invece di "L " modalità. Questo dovrebbe fornire 32 bit per pixel.

Per questo motivo raccomando Numpy anziché PIL.

Di seguito è riportata una riscrittura della funzione di soglia utilizzando Numpy anziché PIL, e ottengo il risultato corretto/previsto. Si noti che creo la mia immagine integrale usando un array uint32. Ho usato lo stesso esempio esatto C su Github che si è utilizzato per la traduzione:

import numpy as np 

def adaptive_thresh(input_img): 

    h, w = input_img.shape 

    S = w/8 
    s2 = S/2 
    T = 15.0 

    #integral img 
    int_img = np.zeros_like(input_img, dtype=np.uint32) 
    for col in range(w): 
     for row in range(h): 
      int_img[row,col] = input_img[0:row,0:col].sum() 

    #output img 
    out_img = np.zeros_like(input_img)  

    for col in range(w): 
     for row in range(h): 
      #SxS region 
      y0 = max(row-s2, 0) 
      y1 = min(row+s2, h-1) 
      x0 = max(col-s2, 0) 
      x1 = min(col+s2, w-1) 

      count = (y1-y0)*(x1-x0) 

      sum_ = int_img[y1, x1]-int_img[y0, x1]-int_img[y1, x0]+int_img[y0, x0] 

      if input_img[row, col]*count < sum_*(100.-T)/100.: 
       out_img[row,col] = 0 
      else: 
       out_img[row,col] = 255 

    return out_img 

output

+0

Mi ci è voluto un po 'per accettare questa risposta dato che sono stato occupato, ma sì! Non mi sono reso conto che stavano aggiungendo valori oltre 255 e che l'immagine integrale è solo una rappresentazione astratta dei dati, grazie mille! –