How To Make Extraction Of Connected Components In C#
Extraction of connected components in image processing is a morphological process, where we isolate object to a separate image.
Filter by Category
Extraction of connected components in image processing is a morphological process, where we isolate object to a separate image.
Hole filling in image processing is a morphological operation that fills in shapes of black pixels surrounded by white pixels.
Boundary extraction in image processing is one of the basic morphological algorithms with which we extract only the outline of shown objects.
Opening and closing in image processing are morphological operations which are basically sequences of erosion and dilation operations.
Image dilation is one of the fundamental morphological processes, which we demonstrate it here in C# programming language.
Image erosion is one of the fundamental morphological operations and this tutorial explains how it works and demonstrates it in C#.
This tutorial shows how image watermarking works by implementing it with C# and we describe various purposes that watermarks have as well.
This tutorial shows how to use colors for image segmentation applied in C#. I explain the basics of applying it in different color spaces.
This color image smoothing and sharpening tutorial shows how to apply convolution for blurring and sharpening images with C#.
This guide shows how to apply color histogram equalization with iterative equalization of the image by using nth root or nth power.
Extraction of connected components is a morphological operation in image processing. As its name might suggests, we use it to extract a particular object from an image. It is also one of the most important processes to many automated image analysis applications.
We’ll work with binary images in this guide, with which we’ll gain better understanding of morphological operations in general. However, this doesn’t mean we can’t perform these operations on images with more intensity information, like grayscale or color images.
We can view binary images as a two dimensional array of image data. Therefore if we wanted to work with grayscale or color images, we would have 3 or more dimensional arrays of image data. However there is a downside to piling on more image data to process, which is longer computational time.
It actually works very similar to hole filling process. However, the difference between the two is that we seek foreground pixels here while hole filling seeks background pixels.
If you’re not familiar what I mean by foreground and background pixels, it’s just another way of calling white and black pixels. This only applies for binary images, since they only have these two intensities.
Morphological operations are non-linear operations, where we separate pixels into sets. So when we apply a certain operation, it works for the entire pixel set in the image. In other words, if we want to apply an operation on a specific object, like we’re want to do with this extraction, we need to isolate it on a separate image.
Furthermore, extraction of connected components is based on dilation process. All that we need is the location of one pixel, which is a part of the object we’re trying to extract. We then iterate dilation from that pixel and limit it to the borders of the object.
This process stops when we have all the connected pixels of an object on a separate image.
public static Bitmap Extract(this Bitmap image, int start_x, int start_y)
{
int w = image.Width;
int h = image.Height;
BitmapData image_data = image.LockBits(
new Rectangle(0, 0, w, h),
ImageLockMode.ReadOnly,
PixelFormat.Format24bppRgb);
int bytes = image_data.Stride * image_data.Height;
byte[] buffer = new byte[bytes];
Marshal.Copy(image_data.Scan0, buffer, 0, bytes);
image.UnlockBits(image_data);
byte[] temp = new byte[bytes];
byte[] result = new byte[bytes];
//seed point
for (int c = 0; c < 3; c++)
{
temp[start_x * 3 + start_y * image_data.Stride + c] = 255;
}
while (true)
{
//iterate across the image with structuring element
for (int i = 1; i < w - 1; i++)
{
for (int j = 1; j < h - 1; j++)
{
//position of the structuring element center
int position = i * 3 + j * image_data.Stride;
//set up structuring element
for (int k = -1; k < 2; k++)
{
for (int l = -1; l < 2; l++)
{
//position of pixel overlaped by structuring element
int se_pos = position + k * 3 + l * image_data.Stride;
if (Structuring_Element.Vals[k + 1, l + 1] == 1 && buffer[se_pos] > 0)
{
for (int c = 0; c < 3; c++)
{
result[se_pos + c] = Math.Max(temp[position], result[se_pos]);
}
}
}
}
}
}
int difference = 0;
for (int i = 0; i < bytes; i++)
{
if (result[i] != temp[i])
{
temp[i] = result[i];
difference++;
}
}
if (difference == 0)
{
break;
}
}
Bitmap res_img = new Bitmap(w, h);
BitmapData res_data = res_img.LockBits(
new Rectangle(0, 0, w, h),
ImageLockMode.WriteOnly,
PixelFormat.Format24bppRgb);
Marshal.Copy(result, 0, res_data.Scan0, bytes);
res_img.UnlockBits(res_data);
return res_img;
}
I hope this tutorial was helpful making things about extracting objects from image understandable.
You can also download the demo project and try it out yourself. But beware, it takes a little time to process the image. The bigger the input image and larger the object, more time it will take.