Merry Xmas
Image algorithms demo [2,6 MB zip]
1.Calculate the initial average of the current treshold value. Set this value to the
average of the four corner pixels average value.
It took five iterations to calculate the iterative optimal treshold value for the infamous Lenna image, calculated to be 162 in pixel intensity. For an average picture one would expect the value to be above 140 - 180, if the picture is grayscale image with good contrast.
Result:
IMPLEMENTATION - OptimalTresholdFilter.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ImageAlgorithms.Filters.Treshold
{
public class OptimalTresholdFilter : ImageFilterBase
{
int objectPixelSum = 0;
int backgroundPixelSum = 0;
int currentTresholdValue = 0;
int nextTresholdValue = 0;
int objectPixelsCount = 0;
int backgroundPixelCount = 0;
public OptimalTresholdFilter()
{
Header = "Optimal treshold filter";
FilterType = FilterTypeEnum.TresholdFilter;
}
public override void FilterProcessImage(int width, int height)
{
//base.FilterProcessImage(width, height);
//Read first four pixels (edges of image)
//Calculate the average of object pixels and background pixels
//Let avg+1 = average of background pixels and object pixels
//if avg+1 and avg is the same, stop, else continue.
CalculateAverage(width, height, 0);
DisplayTresholdImage(width, height);
}
private void DisplayTresholdImage(int width, int height)
{
for (int i = 0; i < width; i++)
{
for (int j = 0; j < height; j++)
{
int position = (j*width) + i;
if (TemporaryImageData[i, j] > nextTresholdValue)
{
ResultingImageData[position] = 255;
}
else
{
ResultingImageData[position] = 0;
}
}
}
}
private void CalculateAverage(int width, int height, int iteration)
{
InitFilterIteration();
CheckInitialStep(width, height, iteration);
TraverseImageBackgroundForeground(width, height, iteration);
CheckPixelCounts();
CalculateNextTreshold();
if (nextTresholdValue != currentTresholdValue && iteration < 100)
{
currentTresholdValue = nextTresholdValue;
CalculateAverage(width, height, iteration + 1);
}
}
private void CalculateNextTreshold()
{
nextTresholdValue = ((objectPixelSum / objectPixelsCount) +
(backgroundPixelSum / backgroundPixelCount)) / 2;
}
private void TraverseImageBackgroundForeground(int width, int height, int iteration)
{
for (int i = 0; i < width; i++)
{
for (int j = 0; j < height; j++)
{
if (TemporaryImageData[i, j] > currentTresholdValue)
{
AddToObjectPixels(i, j);
}
else
{
if (iteration > 0)
{
AddToBackgroundPixels(i, j);
}
}
}
}
}
private void AddToBackgroundPixels(int i, int j)
{
backgroundPixelSum += TemporaryImageData[i, j];
backgroundPixelCount++;
}
private void AddToObjectPixels(int i, int j)
{
objectPixelSum += TemporaryImageData[i, j];
objectPixelsCount++;
}
private void CheckInitialStep(int width, int height, int iteration)
{
if (iteration == 0)
{
backgroundPixelSum = (TemporaryImageData[0, 0] + TemporaryImageData[width - 1, 0] +
TemporaryImageData[0, height - 1] +
TemporaryImageData[width - 1, height - 1]);
backgroundPixelCount = 4;
currentTresholdValue = backgroundPixelSum / backgroundPixelCount;
}
}
private void CheckPixelCounts()
{
objectPixelsCount = Math.Max(1, objectPixelsCount);
backgroundPixelCount = Math.Max(1, backgroundPixelCount);
}
private void InitFilterIteration()
{
backgroundPixelCount = 0;
objectPixelsCount = 0;
backgroundPixelSum = 0;
objectPixelSum = 0;
}
}
}