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

Mean Filters

How To Use Geometric Mean Filter On Image – C# Guide

Geometric mean filter is one of mean filters we can use processing images in spatial domain. We use C# programming language to apply it here.

Posted on by Andraz Krzisnik
C# Image Processing

How To Use Butterworth Lowpass Filter – C# Guide

We use Butterworth lowpass filter to process images in the frequency domain. And by now, I assume you’re already familiar with Fourier transform and how to use it to...

Posted on by Andraz Krzisnik