### How To Make Adaptive Thresholding Algorithm With C#

Adaptive thresholding operation computes thresholds for each pixel locally and therefore segments images more accurately.

Filter by Category

- C# Tutorial(84)
- C# Image Processing(69)
- Morphological Processes(20)
- Image Processing(16)
- Image Restoration and Reconstruction(16)
- Image Segmentation(13)
- Frequency Domain Filtering(8)
- Color Image Processing(8)
- Image Noise(6)
- Grayscale Morphology(5)
- Thresholding(4)
- Mean Filters(4)
- Order-Statistic Filters(4)
- Morphological Reconstruction(3)
- Edge Detection(3)
- Adaptive Filters(2)
- RGB to HSI Color Model(2)
- Tone and Color Corrections(2)
- Landing Pages(1)
- Point Detection(1)
- Line Detection(1)
- Social Games(1)
- Region Growing Segmentation(1)
- Region Splitting And Merging(1)
- Region Segmentation With K Means Clustering(1)
- Region Segmentation Using Superpixels(1)
- Bandreject Filters(1)
- Bandpass filters(1)
- Notch Filters(1)
- Intensity Slicing and Color Coding(1)
- Color Slicing(1)
- Histogram Processing Color Images(1)
- Color Image Smoothing And Sharpening(1)
- Using Color In Image Segmentation(1)
- Digital Image Watermarking(1)

Back to Latest Articles
###
How To Make Adaptive Thresholding Algorithm With C#

###
How To Make Multilevel Thresholding Algorithm With C#

###
How To Make Otsu Thresholding Algorithm With C#

###
How To Make A Basic Global Thresholding Algorithm – C#

Thresholding

Adaptive thresholding operation computes thresholds for each pixel locally and therefore segments images more accurately.

Thresholding

Multilevel thresholding is an extension of Otsu's method of thresholding, which basically works for an arbitrary number of thresholds.

Thresholding

Otsu thresholding is a global thresholding method, with which we find optimal threshold intensity to ensure the maximum separability.

Thresholding

This tutorial demonstrates how to get optimal threshold value for basic global thresholding operation for segmentation in image processing.

How To Make Adaptive Thresholding Algorithm...

Adaptive thresholding adds next level complexity by computing thresholds for every pixel. In order to do that we’ll to compute histogram values for each pixel by taking into account its surrounding pixels.

In general, noise and nonuniform illumination in the image affect thresholding process performance the most. Therefore, sometimes we need to use a different method for thresholding the image, rather than using a global threshold.

We’re going to use elements of convolution with this one, since we need to isolate image data into pixel neighborhoods. In other words, we’re going to iterate through a neighborhood of each pixel and compute its own threshold.

Before we decide to use this process, you could also try and apply image smoothing or use its edge information to solve your problem. These processes are helpful for reducing noise and separating objects and background more clearly.

As we mentioned already, we need to compute threshold for every pixel neighborhood. Therefore, we’re going to produce an image of threshold values, which will be the same size as the input image.

However, since we’re taking into account surrounding pixels at each point we we’ll need to use zero padding. The reason for this is so we can compute threshold values for pixels in the borders as well.

In case it’s not important if data round the image border is lost to this process, we can also skip the padding step. Because of this, our resulting image is going to have a border of black pixels, since we won’t add data to them.

Let’s get to what we actually need to compute at every pixel in order to get to its threshold. We’re going to use mean and standard deviation for each neighborhood separately. These are the main parts of the formula, which are also the descriptors of average intensity and contrast.

And in case you’re not familiar with the following formulas, the p_{Sxy} stands for normalized histogram value for r_{i} intensity.

As you can see in the following formula for local threshold, we also need additional parameters. The reason for this is because we need to adjust them so we can threshold the whole image optimally. In other words, each image will have different noise levels and illumination, so we need to find these parameters experimentally.

The m_{g} parameter in the formula above stands for global mean intensity value. This is just an average intensity value of the whole image.

We can further improve adaptive thresholding by using additional conditions when we’re thresholding the image. The following formula demonstrates how to do it. Just keep in mind that pixels that will yield TRUE will become white and those that will yield FALSE, will become black.

```
public static Bitmap VariableThresholdingLocalProperties(this Bitmap image, double a, double b)
{
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];`

` byte[] result = new byte[bytes];`

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

` image.UnlockBits(image_data);`

` //Get global mean - this works only for grayscale images`

` double mg = 0;`

` for (int i = 0; i < bytes; i+=3)`

` {`

` mg += buffer[i];`

` }`

` mg /= (w * h);`

` for (int x = 1; x < w - 1; x++)`

` {`

` for (int y = 1; y < h - 1; y++)`

` {`

` int position = x * 3 + y * image_data.Stride;`

` double[] histogram = new double[256];`

` for (int i = -1; i <= 1; i++)`

` {`

` for (int j = -1; j <= 1; j++)`

` {`

` int nposition = position + i * 3 + j * image_data.Stride;`

` histogram[buffer[nposition]]++;`

` }`

` }`

` histogram = histogram.Select(l => l / (w * h)).ToArray();`

` double mean = 0;`

` for (int i = 0; i < 256; i++)`

` {`

` mean += i * histogram[i];`

` }`

` double std = 0;`

` for (int i = 0; i < 256; i++)`

` {`

` std += Math.Pow(i - mean, 2) * histogram[i];`

` }`

` std = Math.Sqrt(std);`

` double threshold = a * std + b * mg;`

` for (int c = 0; c < 3; c++)`

` {`

` result[position + c] = (byte)((buffer[position] > threshold) ? 255 : 0);`

` }`

` }`

` }`

` 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 helped you understand how adaptive thresholding works. There are also other posts about thresholding and other image processing operations on this blog.

You can also **download the demo project** and try it out yourself.

## Comments