C# Tutorial: How To Apply Erosion To An Image


Andraz Krzisnik
C# Tutorial: How To Apply Erosion To An Image

Erosion is a morphological process, where pixels at an object boundaries are removed. Erosion and dilation are a pair of basic morphological transformations, which are completely opposite to one another.

How does it work?

When an image is processed it works with a kernel, which is placed on every pixel of the image. When a kernel is over a certain set of pixels, only the center pixel is evaluated for a change in intensity. All other neighboring pixel are just scanning the surface around it for a change in intensity. If they detect there is a change, the center pixel’s intensity is changed to the lowest intensity detected.

Usually we use erosion on binary images, or in other words images which contain only black and white. It works very well with Sobel edge detection filter, which produces such images, where edges od the objects are highlighted in white, while the background is completely black,

It is also very often used in combination with dilation and holes filling processes. While dilation adds pixels to edges, holes filling gives us an ability to whiten in the object. After these two processes we usually use erosion to get rid of that extra layer of pixels on the edges of our object in the image, so it is of the original size again.

Erosion function breakdown

First part of the function is dedicated to saving all your image data into an array, where we will read the image in numbers.

private Bitmap ErodeImage(Bitmap srcImage)
{
    int width = srcImage.Width;
    int height = srcImage.Height;

    Rectangle canvas = new Rectangle(0, 0, width, height);
    BitmapData srcData = srcImage.LockBits(canvas, ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);

    int bytes = srcData.Stride * srcData.Height;
    byte[] pixelBuffer = new byte[bytes];
    byte[] resultBuffer = new byte[bytes];

    Marshal.Copy(srcData.Scan0, pixelBuffer, 0, bytes);
    srcImage.UnlockBits(srcData);

Conversion to grayscale

Although it is mostly used for binary images, this code works for grayscale aswell.

float rgb;
for (int i = 0; i < bytes; i += 4)
{
    rgb = pixelBuffer[i] * .071f;
    rgb += pixelBuffer[i + 1] * .71f;
    rgb += pixelBuffer[i + 2] * .21f;
    pixelBuffer[i] = (byte)rgb;
    pixelBuffer[i + 1] = pixelBuffer[i];
    pixelBuffer[i + 2] = pixelBuffer[i];
    pixelBuffer[i + 3] = 255;
}

Apply erosion

Save processed data into the second array we created for holding the image data.

int kernelSize = 3;
int kernelOffset = (kernelSize - 1) / 2;
int calcOffset = 0;
int byteOffset = 0;

for (int y = kernelOffset; y < height - kernelOffset; y++)
{
    for (int x = kernelOffset; x < width - kernelOffset; x++)
    {
        byte value = 255;
        byteOffset = y * srcData.Stride + x * 4;
        for (int ykernel = -kernelOffset; ykernel <= kernelOffset; ykernel++)
        {
            for (int xkernel = -kernelOffset; xkernel <= kernelOffset; xkernel++)
            {
                if (kernel[ykernel + kernelOffset,xkernel + kernelOffset] == 1)
                {
                    calcOffset = byteOffset + ykernel * srcData.Stride + xkernel * 4;
                    value = Math.Min(value, pixelBuffer[calcOffset]);
                }
                else
                {
                    continue;
                }
            }
        }
        resultBuffer[byteOffset] = value;
        resultBuffer[byteOffset + 1] = value;
        resultBuffer[byteOffset + 2] = value;
        resultBuffer[byteOffset + 3] = 255;
    }
}

Output processed image

Create a new bitmap to which we copy image data from array that holds processed values.

    Bitmap result = new Bitmap(width, height);
    BitmapData resultData = result.LockBits(canvas, ImageLockMode.WriteOnly, PixelFormat.Format32bppArgb);
    Marshal.Copy(resultBuffer, 0, resultData.Scan0, bytes);
    result.UnlockBits(resultData);
    return result;
}

Downloadable content

Download Project

Now it’s your turn, let me know what you think in the comments below.

Related Articles

C# Tutorial

C# Tutorial: How To Scale Images Without Deforming Them

Let’s Get Started A very basic problem that we face in image processing is how to scale images without making them look deformed when we want to make it of an arbitrary...

Posted on by Andraz Krzisnik
C# Tutorial

How To Use Butterworth Highpass Filter – C# Guide

Butterworth highpass filter is used to filter images in frequency domain. We can control how smooth transition beyond cut off frequency.

Posted on by Andraz Krzisnik