C# How to: Image Erosion and Dilation

Article purpose

The purpose of this article is aimed at exploring the concepts of , , and . In addition this article extends conventional and implementations through partial colour variations of and .

Sample source code

This article is accompanied by a sample source code Visual Studio project which is available for download .

Using the sample application

Included in this article’s sample source code you’ll find a based sample application. The sample application can be used to test and replicate the concepts we explore in this article.

When executing the sample application source/input can selected from the local system by clicking the Load Image button. On the right-hand side of the sample application’s user interface users can adjust the provided controls in order to modify the method of filtering being implemented.

The three labelled Red, Green and Blue relate to whether the relevant colour component will be regarded or not when implementing the configured filter.

Users are required to select an filter: , or . The interface selection is expressed by means of four respectively labelled Dilate, Erode, Open and Closed.

The only other input required from a user comes in the form of selecting the filter intensity/filter size. The dropdown indicated as Filter Size provides the user with several intensity levels ranging from 3×3 to 17×17. Note: Larger filter sizes result in additional processing required when implementing the filter. Large set to implement large sized filters may require more processor cycles.

Resulting filtered can be saved to the local file system by clicking the Save Image button. The screenshot below illustrates the Image Erosion and Dilation sample application in action:

Image_Erosion_Dilation_Sample_Application

Mathematical Morphology

A description of as expressed on :

Mathematical morphology (MM) is a theory and technique for the analysis and processing of geometrical structures, based on , , , and . MM is most commonly applied to , but it can be employed as well on , , , and many other spatial structures.

and -space concepts such as size, , , , and , were introduced by MM on both continuous and . MM is also the foundation of morphological image processing, which consists of a set of operators that transform images according to the above characterizations.

MM was originally developed for , and was later extended to and images. The subsequent generalization to is widely accepted today as MM’s theoretical foundation.

In this article we explore , , as well as and . The implementation of these filters are significantly easier to grasp when compared to most definitions of .

Image Erosion and Dilation

and are implementations of , a subset of . In simpler terms can be defined by this :

Dilation is one of the two basic operators in the area of , the other being . It is typically applied to , but there are versions that work on . The basic effect of the operator on a binary image is to gradually enlarge the boundaries of regions of foreground (i.e. white pixels, typically). Thus areas of foreground pixels grow in size while holes within those regions become smaller.

being a related concept is defined by this :

Erosion is one of the two basic operators in the area of mathematical morphology, the other being . It is typically applied to binary images, but there are versions that work on . The basic effect of the operator on a binary image is to erode away the boundaries of regions of foreground (i.e. white pixels, typically). Thus areas of foreground pixels shrink in size, and holes within those areas become larger.

From the definitions listed above we gather that increases the size of edges contained in an image. In contrast decreases or shrinks the size of an Image’s edges.

Open and Closed Morphology

Building upon the concepts of and this section explores and . A good definition of can be expressed as :

The basic effect of an opening is somewhat like erosion in that it tends to remove some of the foreground (bright) pixels from the edges of regions of foreground pixels. However it is less destructive than erosion in general. As with other morphological operators, the exact operation is determined by a . The effect of the operator is to preserve foreground regions that have a similar shape to this structuring element, or that can completely contain the structuring element, while eliminating all other regions of foreground pixels.

In turn can be defined as :

Closing is similar in some ways to dilation in that it tends to enlarge the boundaries of foreground (bright) regions in an image (and shrink background color holes in such regions), but it is less destructive of the original boundary shape. As with other , the exact operation is determined by a . The effect of the operator is to preserve background regions that have a similar shape to this structuring element, or that can completely contain the structuring element, while eliminating all other regions of background pixels.

Implementing Image Erosion and Dilation

In this article we implement and by iterating each pixel contained within an image. The colour of each pixel is determined by taking into regard a pixel’s neighbouring pixels.

When implementing a pixel’s value is determined by comparing neighbouring pixels’ colour values, determining the highest colour value expressed amongst neighbouring pixels.

In contrast to we implement by also inspecting neighbouring pixels’ colour values, determining the lowest colour value expressed amongst neighbouring pixels.

In addition to conventional and the sample source code provides the ability to perform  and targeting only specific colour components. The result of specific colour and produces images which express the effects of and only in certain colours. Depending on filter parameters specified edges appear to have a coloured glow or shadow.

The sample source code provides the definition for the DilateAndErodeFilter , targeting the class. The following code snippet details the implementation of the DilateAndErodeFilter :

public static Bitmap DilateAndErodeFilter(
                           this Bitmap sourceBitmap,  
                           int matrixSize, 
                           MorphologyType morphType, 
                           bool applyBlue = true, 
                           bool applyGreen = true, 
                           bool applyRed = true )  
{
    BitmapData sourceData =  
               sourceBitmap.LockBits(new Rectangle (0, 0, 
               sourceBitmap.Width, sourceBitmap.Height), 
               ImageLockMode.ReadOnly,  
               PixelFormat.Format32bppArgb); 

byte[] pixelBuffer = new byte[sourceData.Stride * sourceData.Height];
byte[] resultBuffer = new byte[sourceData.Stride * sourceData.Height];
Marshal.Copy(sourceData.Scan0, pixelBuffer, 0, pixelBuffer.Length);
sourceBitmap.UnlockBits(sourceData);
int filterOffset = (matrixSize - 1) / 2; int calcOffset = 0;
int byteOffset = 0;
byte blue = 0; byte green = 0; byte red = 0;
byte morphResetValue = 0;
if (morphType == MorphologyType.Erosion) { morphResetValue = 255; }
for (int offsetY = filterOffset; offsetY < sourceBitmap.Height - filterOffset; offsetY++) { for (int offsetX = filterOffset; offsetX < sourceBitmap.Width - filterOffset; offsetX++) { byteOffset = offsetY * sourceData.Stride + offsetX * 4;
blue = morphResetValue; green = morphResetValue; red = morphResetValue;
if (morphType == MorphologyType.Dilation) { for (int filterY = -filterOffset; filterY <= filterOffset; filterY++) { for (int filterX = -filterOffset; filterX <= filterOffset; filterX++) { calcOffset = byteOffset + (filterX * 4) + (filterY * sourceData.Stride);
if (pixelBuffer[calcOffset] > blue) { blue = pixelBuffer[calcOffset]; }
if (pixelBuffer[calcOffset + 1] > green) { green = pixelBuffer[calcOffset + 1]; }
if (pixelBuffer[calcOffset + 2] > red) { red = pixelBuffer[calcOffset + 2]; } } } } else if (morphType == MorphologyType .Erosion) { for (int filterY = -filterOffset; filterY <= filterOffset; filterY++) { for (int filterX = -filterOffset; filterX <= filterOffset; filterX++) { calcOffset = byteOffset + (filterX * 4) + (filterY * sourceData.Stride);
if (pixelBuffer[calcOffset] < blue) { blue = pixelBuffer[calcOffset]; }
if (pixelBuffer[calcOffset + 1] < green) { green = pixelBuffer[calcOffset + 1]; }
if (pixelBuffer[calcOffset + 2] < red) { red = pixelBuffer[calcOffset + 2]; } } } }
if (applyBlue == false ) { blue = pixelBuffer[byteOffset]; }
if (applyGreen == false ) { green = pixelBuffer[byteOffset + 1]; }
if (applyRed == false ) { red = pixelBuffer[byteOffset + 2]; }
resultBuffer[byteOffset] = blue; resultBuffer[byteOffset + 1] = green; resultBuffer[byteOffset + 2] = red; resultBuffer[byteOffset + 3] = 255; } }
Bitmap resultBitmap = new Bitmap (sourceBitmap.Width, sourceBitmap.Height);
BitmapData resultData = resultBitmap.LockBits(new Rectangle (0, 0, resultBitmap.Width, resultBitmap.Height), ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);
Marshal.Copy(resultBuffer, 0, resultData.Scan0, resultBuffer.Length);
resultBitmap.UnlockBits(resultData);
return resultBitmap; }

Implementing Open and Closed Morphology

The sample source code implements by first implementing on a source image, the resulting image is then filtered by implementing .

In a reverse fashion is achieved by first implementing on a source image, which is then further filtered by implementing .

The sample source code defines the OpenMorphologyFilter and CloseMorphologyFilter , both targeting the class. The implementation as follows:

public static Bitmap OpenMorphologyFilter(
                            this Bitmap sourceBitmap, 
                            int matrixSize,
                            bool applyBlue = true, 
                            bool applyGreen = true, 
                            bool applyRed = true ) 
{ 
    Bitmap resultBitmap = 
           sourceBitmap.DilateAndErodeFilter(
                        matrixSize, MorphologyType.Erosion, 
                        applyBlue, applyGreen, applyRed); 

resultBitmap = resultBitmap.DilateAndErodeFilter( matrixSize, MorphologyType.Dilation, applyBlue, applyGreen, applyRed);
return resultBitmap; }
public static Bitmap CloseMorphologyFilter( this Bitmap sourceBitmap, int matrixSize, bool applyBlue = true, bool applyGreen = true, bool applyRed = true ) { Bitmap resultBitmap = sourceBitmap.DilateAndErodeFilter( matrixSize, MorphologyType.Dilation, applyBlue, applyGreen, applyRed);
resultBitmap = resultBitmap.DilateAndErodeFilter( matrixSize, MorphologyType.Erosion, applyBlue, applyGreen, applyRed);
return resultBitmap; }

Sample Images

The original source image used to create all of the sample images in this article has been licensed under the Creative Commons Attribution-Share Alike 3.0 Unported, 2.5 Generic, 2.0 Generic and 1.0 Generic license. The original image is attributed to Kenneth Dwain Harrelson and can be downloaded from .

The Original Image

Monarch_In_May

Image Dilation 3×3 Blue

Image Dilation 3x3 Blue

Image Dilation 3×3 Blue, Green

Image Dilation 3x3 Blue, Green

Image Dilation 3×3 Green

Image Dilation 3x3 Green

Image Dilation 3×3 Red

Image Dilation 3x3 Red

Image Dilation 3×3 Red, Blue

Image Dilation 3x3 Red, Blue

Image Dilation 3×3 Red, Green, Blue

Image Dilation 3x3 Red, Green, Blue

Image Dilation 13×13 Blue

Image Dilation 13x13 Blue

Image Erosion 3×3 Green, Blue

Image Erosion 3x3 Green, Blue

Image Erosion 3×3 Green

Image Erosion 3x3 Green

Image Erosion 3×3 Red

Image Erosion 3x3 Red

Image Erosion 3×3 Red, Blue

Image Erosion 3x3 Red, Blue

Image Erosion 3×3 Red, Green

Image Erosion 3x3 Red, Green

Image Erosion 3×3 Red, Green, Blue

Image Erosion 3x3 Red, Green, Blue

Image Erosion 9×9 Green

Image Erosion 9x9 Green

Image Erosion 9×9 Red

Image Erosion 9x9 Red

Image Open Morphology 11×11 Green

Image Open Morphology 11x11 Green

Image Open Morphology 11×11 Green Blue

Image Open Morphology 11x11 Green Blue

Image Open Morphology 11×11 Red

Image Open Morphology 11x11 Red

Image Open Morphology 11×11 Red, Blue

Image Open Morphology 11x11 Red, Blue

Related Articles and Feedback

Feedback and questions are always encouraged. If you know of an alternative implementation or have ideas on a more efficient implementation please share in the comments section.

I’ve published a number of articles related to imaging and images of which you can find URL links here:

31 Responses to “C# How to: Image Erosion and Dilation”



  1. 1 C# How to: Boolean Edge Detection | Software by Default Trackback on June 1, 2013 at 2:09 AM
  2. 2 C# How to: Gradient Based Edge Detection | Software by Default Trackback on June 1, 2013 at 4:47 PM
  3. 3 C# How to: Image Cartoon Effect | Software by Default Trackback on June 2, 2013 at 4:13 PM
  4. 4 C# How to: Sharpen Edge Detection | Software by Default Trackback on June 7, 2013 at 5:12 AM
  5. 5 C# How to: Calculating Gaussian Kernels | Software by Default Trackback on June 8, 2013 at 10:59 AM
  6. 6 C# How to: Image Blur | Software by Default Trackback on June 9, 2013 at 10:20 PM
  7. 7 C# How to: Image Transform Rotate | Software by Default Trackback on June 16, 2013 at 10:40 AM
  8. 8 C# How to: Image Transform Shear | Software by Default Trackback on June 16, 2013 at 5:45 PM
  9. 9 C# How to: Compass Edge Detection | Software by Default Trackback on June 22, 2013 at 9:35 PM
  10. 10 C# How to: Oil Painting and Cartoon Filter | Software by Default Trackback on June 30, 2013 at 10:47 AM
  11. 11 C# How to: Stained Glass Image Filter | Software by Default Trackback on June 30, 2013 at 10:50 AM
  12. 12 C# How to: Morphological Edge Detection | Software by Default Trackback on June 30, 2013 at 2:02 PM
  13. 13 C# How to: Image Colour Average | Software by Default Trackback on June 30, 2013 at 2:20 PM
  14. 14 C# How to: Image Unsharp Mask | Software by Default Trackback on June 30, 2013 at 2:28 PM
  15. 15 C# How to: Image Median Filter | Software by Default Trackback on June 30, 2013 at 3:16 PM
  16. 16 C# How to: Difference Of Gaussians | Software by Default Trackback on June 30, 2013 at 3:27 PM
  17. 17 C# How to: Image Edge Detection | Software by Default Trackback on June 30, 2013 at 3:33 PM
  18. 18 C# How to: Image Convolution | Software by Default Trackback on June 30, 2013 at 3:55 PM
  19. 19 C# How to: Generate a Web Service from WSDL | Software by Default Trackback on June 30, 2013 at 4:08 PM
  20. 20 C# How to: Decoding/Converting Base64 strings to Bitmap images | Software by Default Trackback on June 30, 2013 at 4:14 PM
  21. 21 C# How to: Bitmap Colour Substitution implementing thresholds | Software by Default Trackback on July 6, 2013 at 4:33 PM
  22. 22 C# How to: Swapping Bitmap ARGB Colour Channels | Software by Default Trackback on July 6, 2013 at 5:02 PM
  23. 23 C# How to: Image filtering by directly manipulating Pixel ARGB values | Software by Default Trackback on July 8, 2013 at 2:57 AM
  24. 24 C# How to: Image ASCII Art | Software by Default Trackback on July 14, 2013 at 7:22 AM
  25. 25 C# How to: Weighted Difference of Gaussians | Software by Default Trackback on July 14, 2013 at 8:11 PM
  26. 26 C# How to: Image Boundary Extraction | Software by Default Trackback on July 21, 2013 at 10:24 AM
  27. 27 C# How to: Image Abstract Colours Filter | Software by Default Trackback on July 28, 2013 at 7:41 PM
  28. 28 C# How to: Fuzzy Blur Filter | Software by Default Trackback on August 9, 2013 at 6:39 AM
  29. 29 C# How to: Image Distortion Blur | Software by Default Trackback on August 9, 2013 at 10:13 PM
  30. 30 C# How to: Standard Deviation Edge Detection | Software by Default Trackback on August 8, 2015 at 8:10 AM
  31. 31 C# How to: Min/Max Edge Detection | Software by Default Trackback on August 9, 2015 at 11:30 AM

Leave a comment




Dewald Esterhuizen

Blog Stats

  • 869,810 hits

Enter your email address to follow and receive notifications of new posts by email.

Join 228 other subscribers

Archives

RSS SoftwareByDefault on MSDN

  • An error has occurred; the feed is probably down. Try again later.