The introduction of erosion, expansion in C, C ++

I have a theoretical understanding of how binary dilatation is done.

AFAIK, if my SE (structuring element) is

0 1 1 1. 

Where. represents the center and my image (binary it)

 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 

therefore, the result of dilation is

 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 

I got the result by moving the image in the direction of 0, +1 (up) and -1 (left), according to SE, and combining all three of these shifts.

Now I need to figure out how to implement this in C, C ++. I am not sure how to start and how to accept union of sets. I was thinking of presenting the original image, the three shifted images, and the final image obtained by combining; all using a matrix.

Is there any place where I can get an approximate solution to start with or any ideas to continue?

Thanks.

+6
c ++ image-processing mathematical-morphology
source share
4 answers

There are tons of implementation examples out there. Google is your friend :)

EDIT
Below is the pseudo-code of the process (very similar to doing convolution in 2D). I am sure there is a smarter way to do this:

 // 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; } } } 

The above code is based on this tutorial (check the source code at the end of the page).


EDIT2 :

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

The idea is that we want to superimpose a kernel mask (nxn size) centered at sz (half the size of the mask) on the current image pixel located in (X, Y), and then just get the pixel intensities where the mask value is one (we add them to the list). After you extracted all the neighbors for this pixel, we set the maximum output pixel for this list (maximum intensity) for dilatation and mines for erosion (of course, this only works for grayscale and binary mask images)
The X / Y and I / J indices in the above statement are supposed to start at 0. If you prefer, you can always rewrite the I / J indices in terms of half the mask size (from -sz to + sz) with a small change (the way I use the tutorial I'm connected with) ...


An example :
Consider this 3x3 kernel mask placed and centered on a pixel (X, Y), and see how we cross the neighborhood around it:

  -------------------- | | | | 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) ); | | | | -------------------- 
+10
source share

Perhaps the best way to look at this is to create an output extension pixel. For the corresponding pixel in the image, align the structuring element so that the beginning of the structuring element is on that pixel of the image. If there is any overlap, set the output pixel of the extension in this place to 1, otherwise set it to 0.

Thus, this can be done by simply recounting each pixel in the image and checking if the element with the correctly shifted structuring overlaps the image. This means that you will likely have 4 nested loops: x img, y img, x se, y se. Therefore, for each pixel in the image, you iterate over the pixels of the structuring element and see if there is any overlap. This may not be the most efficient algorithm, but it is probably the simplest.

Also, I think your example is incorrect. Dilation depends on the origin of the structuring element. If the origin ...

in the upper left zero: you need to shift the image (-1, -1), (-1,0) and (0, -1), giving:

 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 

in the lower right corner: you need to shift the image (0,0), (1,0) and (0,1), indicating:

 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 uses gender ((size (SE) +1) / 2) as the source of SE, so in this case it will use the top left pixel of SE. You can verify this using the imdilate MATLAB function.

+2
source share
+1
source share
 /* 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 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 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 */ 
0
source share

All Articles