Navigation

Related Articles

Back to Latest Articles

How To Make Skeletonization With C#

Skeletonization is a morphological process in image processing, which extracts the center lines of all shapes, which look like their skeleton


Andraz Krzisnik
How To Make Skeletonization With C#

Skeletonization is a morphological operation in image processing with which we can extract the skeleton of shapes in binary images. Furthermore, skeletons are basically lines that lie in the middle of shapes.

Binary images have pixels with only two possible intensities, meaning they can be either black or white. Or if we put it in morphological terms, background and foreground pixels.

Furthermore, we divide image data into sets when we’re working with morphological processes. So in our case, we’re going to divide them into two sets, one for each color.

skeletonization example
Skeletonization example

We can define the skeleton of a shape by placing a circle inside it. Therefore, if this circle is as large as it can be while still being inside the shape, its center would be a part of the skeleton. However, the size of this circle may vary depending on its position.

When this circle is of maximum size on any position, it touches boundary of the shape at two or more different places.

How does skeletonization in image processing work?

Unfortunately, it’s not that simple when it comes to processing pixels. However, we’re going to use morphological processes, we’ve covered before. We can skeletonize an image by using erosion and opening operations.

The trick here is to erode an image, and subtract the results of opening from it to get one part of the skeleton. Furthermore, we need to repeat this process, by further eroding and opening the image. And finally, we stop this iteration when an opening results to an empty image.

We get the skeleton of the image by combining the results of all steps where we subtracted opening from erosion. This may be difficult to grasp at first, but don’t worry, the function for this process if fairly simple.

And in case you’re not familiar with opening operation, we essentially apply erosion and then dilation to the result.

skeletonization in image processing
Skeletonization process

We can also reconstruct the skeletonized image, but we need to have each of the step stored separately. So we can do this by applying dilation at each of the steps and combining them to form the image.

Code

I will include the function for skeletonization only. Therefore, I’d like to recommend that you check out the entire project. However, functions that aren’t going to be included in this post are for erosion and dilation.

public static Bitmap Skeletonize(this Bitmap image)
     {
         int w = image.Width;
         int h = image.Height;

         BitmapData image_data = image.LockBits(
             new Rectangle(0, 0, w, h),
             ImageLockMode.ReadOnly,
             PixelFormat.Format8bppIndexed);

         int bytes = image_data.Stride * image_data.Height;
         byte[] buffer = new byte[bytes];
         byte[] temp = new byte[bytes];
         byte[] result = new byte[bytes];

         Marshal.Copy(image_data.Scan0, buffer, 0, bytes);
         image.UnlockBits(image_data);

         while (true)
         {
             temp = buffer.Erode(w, h);
             int sum = temp.Sum(x => (int)x);

             if (sum == 0)
             {
                 break;
             }

             temp = temp.Dilate(w, h);

             for (int i = 0; i < bytes; i++)
             {
                 result[i] += (byte)(buffer[i] - temp[i]);
             }

             buffer = buffer.Erode(w, h);
         }

         Bitmap res_img = new Bitmap(w, h);
         BitmapData res_data = res_img.LockBits(
             new Rectangle(0, 0, w, h),
             ImageLockMode.WriteOnly,
             PixelFormat.Format8bppIndexed);
         Marshal.Copy(result, 0, res_data.Scan0, bytes);
         res_img.UnlockBits(res_data);
         return res_img;
     }

Conclusion

I hope this guide was helpful in understanding skeletonization process. As I said before, I’m including a download link to this demo project.

Related Articles

Frequency Domain Filtering

How To Use Bandreject Filters – C# Guide

We use bandreject filters to attenuate a ring of frequencies around the center of a 2 dimensional frequency map. Now what does all that mean? We’re going to focus on...

Posted on by Andraz Krzisnik
Edge Detection

How To Make Basic Edge Detection Algorithm With C#

Edge detection is a segmentation technique in image processing for extracting object boundaries based on abrupt intensity changes.

Posted on by Andraz Krzisnik