Navigation

Related Articles

Back to Latest Articles

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

Linked Lists

How To Use Linked Lists In C# – Made Easy

Linked lists are a type of list that allow us to traverse its elements without using their index positions.

Posted on by Andraz Krzisnik
Digital Image Watermarking

How To Make Image Watermarking Work With C#

This tutorial shows how image watermarking works by implementing it with C# and we describe various purposes that watermarks have as well.

Posted on by Andraz Krzisnik