2015-04-07 11 views
7

Obecnie pracuję nad implementacją algorytmu progowania nazwanego Bradley Adaptive Thresholding.Adaptacyjny algorytm progowania Bradley'a

Podążałem głównie za dwoma linkami, aby dowiedzieć się, jak wdrożyć ten algorytm. Z powodzeniem udało mi się również wdrożyć dwa inne algorytmy progowania, głównie Otsu's Method i Balanced Histogram Thresholding.

Oto dwa łącza, które śledziłem w celu utworzenia algorytmu 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

Oto fragment mojego kodu źródłowego w Python gdzie Używam algorytm i zapisywania obrazu. Używam Python Imaging Library i żadnych innych narzędzi do wykonania tego, co chcę zrobić.

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 

Oto fragment mojego kodu, który ilustruje implementację tych zestawów i metod, których wcześniej nie widziałeś.

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)] 

Na koniec przedstawiamy obrazy wejściowe i wyjściowe. Są to te same obrazy, które są używane w oryginalnym artykule badawczym w pierwszym linku, który ci podałem. Uwaga: Obraz wyjściowy jest prawie całkowicie biały i może być trudny do zobaczenia, ale mimo to dostarczyłem go na wypadek, gdyby ktoś chciał go mieć jako punkt odniesienia.

Input Image Output Image

+1

Co nie działa, prawidłowe generowanie obrazu wyjściowego? Czy masz jakieś nie-wizualne testy? – Ashalynd

+0

Tak, poprawne generowanie obrazu wyjściowego nie działa, użyłem dokładnie tego samego obrazu, którego używał papier badawczy do jego testu, a obraz wyjściowy jest całkowicie biały i nie wygląda dokładnie tak, jak obraz wyjściowy artykułu badawczego.Jeśli chodzi o testy nie wizualne, nie jestem pewien, co masz na myśli. –

Odpowiedz

8

Nie można tworzyć integralny obraz z PIL sposób, że robisz to dlatego, że obraz, który pakuje dane do nie może przyjąć wartości ponad 255. Wartości w integralny obraz uzyskać bardzo duża ponieważ są to sumy pikseli powyżej i po lewej stronie (patrz strona 3 białej księgi). Będą rosły o wiele większe niż 255, więc do ich przechowywania potrzebujesz 32 bitów na piksel.

Można to przetestować, tworząc obraz PIL w trybie "L", a następnie ustawiając piksel na 1000000 lub dużą liczbę. Wtedy, kiedy odczytywał wartość, zwróci 255.

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

EDIT: Po zapoznaniu się z dokumentacją PIL, może być w stanie używać PIL jeśli tworzyć integralną obrazu w trybie „I” zamiast „L "tryb. Powinno to zapewnić 32 bity na piksel.

Z tego powodu zalecam Numpy zamiast PIL.

Poniżej znajduje się przepisanie funkcji progowej za pomocą Numpy zamiast PIL, a otrzymam poprawny/oczekiwany wynik. Zauważ, że tworzę swój integralny obraz za pomocą tablicy uint32. Użyłem dokładnie tego samego przykładu C na Github, który został użyty do tłumaczenia:

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

Zajęło mi trochę czasu, aby zaakceptować tę odpowiedź, ponieważ byłem zajęty, ale tak! Nie zdawałem sobie sprawy, że dodają wartości powyżej 255, a integralny obraz to tylko abstrakcyjna reprezentacja danych, dziękuję bardzo! –