2009-09-24 16 views
6

Mam teoretyczne zrozumienie, jak wykonuje się dylatację w obrazie binarnym.implementacja erozji, rozszerzenie w C, C++

AFAIK, Jeśli mój SE (elementem struktury) jest to

0 1 
1 1. 

gdzie. stanowi centrum, a mój obraz (binarny jest to)

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

więc wynikiem dylatacji jest

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

mam powyżej wyniku poprzez przesunięcie obrazu w 0, +1 (w górę) i i - 1 (lewy) kierunek, według SE, i połączenie wszystkich tych trzech zmian.

Teraz muszę dowiedzieć się, jak zaimplementować to w C, C++. Nie wiem, jak zacząć i jak wziąć zestaw związków. Myślałem o reprezentowaniu oryginalnego obrazu, trzech przesuniętych obrazów i końcowego obrazu uzyskanego przez wzięcie zjednoczenia; wszystko za pomocą macierzy.

Czy jest jakieś miejsce, w którym mogę uzyskać przykładowe rozwiązanie lub pomysły na kontynuowanie?

Dzięki.

Odpowiedz

10

Istnieje mnóstwo przykładowych wdrożeń tam .. Google jest twoim przyjacielem :)

EDIT
Poniżej znajduje się pseudo-kod procesu (bardzo podobny do robienia splotu w 2D). Im pewien, że są bardziej sprytny sposób, aby to zrobić:

// grayscale image, binary mask 
void morph(inImage, outImage, kernel, type) { 
// half size of the kernel, kernel size is n*n (easier if n is odd) 
sz = (kernel.n - 1)/2; 

for X in inImage.rows { 
    for Y in inImage.cols { 

    if (isOnBoundary(X,Y, inImage, sz)) { 
    // check if pixel (X,Y) for boundary cases and deal with it (copy pixel as is) 
    // must consider half size of the kernel 
    val = inImage(X,Y);  // quick fix 
    } 

    else { 
    list = []; 

    // get the neighborhood of this pixel (X,Y) 
    for I in kernel.n { 
    for J in kernel.n { 
     if (kernel(I,J) == 1) { 
     list.add(inImage(X+I-sz, Y+J-sz)); 
     } 
    } 
    } 

    if type == dilation { 
    // dilation: set to one if any 1 is present, zero otherwise 
    val = max(list); 
    } else if type == erosion { 
    // erosion: set to zero if any 0 is present, one otherwise 
    val = min(list); 
    } 
    } 

    // set output image pixel 
    outImage(X,Y) = val; 
    } 
} 
} 

Powyższy kod jest oparty na tej tutorial (sprawdź kod źródłowy na końcu strony).


EDIT2:

list.add (inImage (X + I-SZ, T + J sz));

Chodzi o to, że chcemy nałożyć maskę jądra (wielkość NxN) skoncentrowany na sz (pół rozmiaru maski) w sprawie bieżącego piksela obrazu znajduje się w punkcie (x, y), a następnie po prostu intensywności pikseli, w których wartość maski wynosi 1 (dodajemy je do listy). Po wyodrębnieniu wszystkich sąsiadów dla tego piksela, ustawiamy piksel obrazu wyjściowego na maksimum tej listy (maksimum intensywności) dla dylatacji i min dla erozji (oczywiście działa to tylko dla obrazów w skali szarości i maski binarnej)
Wskaźniki zarówno X/Y, jak i I/J w powyższym stwierdzeniu zaczynają się od 0. Jeśli wolisz, możesz zawsze przepisać indeksy I/J pod względem połowy wielkości maski (od -sz do + sz) z niewielką zmianą (sposób, w jaki korzysta z samouczka, do którego się przyłączyłem) ...


Przykład:
Rozważmy tę maskę jądra 3x3 umieszczony i skoncentrowany na piksel (X, Y), i zobaczyć, jak możemy przemierzać okolicę wokół niego:

-------------------- 
|  |  |  | sz = 1; 
--------------------  for (I=0 ; I<3 ; ++I) 
|  | (X,Y) |  |  for (J=0 ; J<3 ; ++J) 
--------------------   vect.push_back(inImage.getPixel(X+I-sz, Y+J-sz)); 
|  |  |  | 
-------------------- 
+0

A co z przypadkiem, w którym mamy rozmiar jądra MxN = 1x3 gdzie M to szerokość, a N to wysokość? – svlada

+0

Kod miał być jedynie zarysem, a nie rzeczywistą implementacją. Ale jeśli przyjrzysz się uważnie, zobaczysz, że mam do czynienia tylko z jądrami N * N, gdzie N jest liczbą nieparzystą. – Amro

+0

:) Tak, widzę to. Chciałem tylko powiedzieć, że możesz ulepszyć swój kod, dodając kernelWidth kernelHeght i sprawdzając granice. – svlada

2

Być może lepszym sposobem wyglądać w ten sposób można uzyskać wyjściowy piksel rozszerzenia. W przypadku odpowiedniego piksela na obrazie dopasuj element strukturyzacji tak, aby początek elementu strukturyzacji znajdował się w tym pikselu obrazu. Jeśli zachodzi jakikolwiek nakładki, ustaw piksel wyjściowy dylatacji w tej lokalizacji na 1, w przeciwnym razie ustaw na 0.

Można to zrobić poprzez zapętlenie każdego piksela obrazu i sprawdzenie, czy prawidłowo przesunięta struktura element pokrywa się z obrazem. Oznacza to, że prawdopodobnie masz 4 zagnieżdżone pętle: x img, y img, x se, y se. Tak więc dla każdego piksela obrazu pętli nad pikselami elementu strukturyzacji i zobacz, czy istnieje nakładanie się. Może to nie być najskuteczniejszy algorytm, ale prawdopodobnie jest najprostszy.

Ponadto, Twój przykład jest niepoprawny. Rozszerzenie zależy od pochodzenia elementu strukturyzującego. Jeśli pochodzenie jest ...

w lewym górnym rogu do zera: trzeba przesunąć obraz (-1, -1), (-1,0) i (0, -1) podając:

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

w prawym dolnym rogu: trzeba przesunąć obraz (0,0), (1,0) i (0,1) podając:

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

MATLAB używa podłogową ((rozmiar (SE) +1)/2) jako pochodzenie SE, więc w tym przypadku wykorzysta górny lewy piksel SE. Możesz to sprawdzić, korzystając z funkcji MATLAB imdilate.

0
/* structure of the image variable 
* variable n stores the order of the square matrix */ 

typedef struct image{ 
     int mat[][]; 
     int n; 
     }image; 


/* function recieves image "to dilate" and returns "dilated"* 
* structuring element predefined: 
*    0 1 0 
*    1 1 1 
*    0 1 0 
*/ 

image* dilate(image* to_dilate) 
{ 
     int i,j; 
     int does_order_increase; 
     image* dilated; 

     dilated = (image*)malloc(sizeof(image)); 
     does_order_increase = 0; 

/* checking whether there are any 1's on d border*/  

     for(i = 0 ; i<to_dilate->n ; i++) 
     { 
      if((to_dilate->a[0][i] == 1)||(to_dilate->a[i][0] == 1)||(to_dilate->a[n-1][i] == 1)||(to_dilate->a[i][n-1] == 1)) 
      { 
       does_order_increase = 1; 
       break; 
      } 
     } 

/* size of dilated image initialized */  

     if(does_order_increase == 1) 
      dilated->n = to_dilate->n + 1; 
     else 
      dilated->n = to_dilate->n; 

/* dilating image by checking every element of to_dilate and filling dilated * 
* does_order_increase serves to cope with adjustments if dilated 's order increase */ 

     for(i = 0 ; i<to_dilate->n ; i++) 
     { 
      for(j = 0 ; j<to_dilate->n ; j++) 
      { 
       if(to_dilate->a[i][j] == 1) 
       { 
        dilated->a[i + does_order_increase][j + does_order_increase] = 1; 
        dilated->a[i + does_order_increase -1][j + does_order_increase ] = 1; 
        dilated->a[i + does_order_increase ][j + does_order_increase -1] = 1; 
        dilated->a[i + does_order_increase +1][j + does_order_increase ] = 1; 
        dilated->a[i + does_order_increase ][j + does_order_increase +1] = 1; 
       } 
      } 
     } 

/* dilated stores dilated binary image */ 

     return dilated; 
} 

/* end of dilation */