Link: https://ieeexplore.ieee.org/document/4310076
#define OBJECT 255
#define BACKGROUND 0
void RunOtsu(unsigned char* srcImage, unsigned char* binaryImage, int imageWidth, int imageHeight)
{
int findedThreshold = FindThresholdBasedOnGrayLevelHistogram(srcImage, imageWidth, imageHeight);
RunFixedThresholding(srcImage, binaryImage, imageWidth, imageHeight, findedThreshold);
}
int FindThresholdBasedOnGrayLevelHistogram(unsigned char* srcImage, const int imageWidth, const int imageHeight)
{
register int m;
int totalSize = imageWidth*imageHeight;
float cumulativeHistogram[256] = {0.0f, };
for(m=0; m<totalSize; m++)
{
int values = srcImage[m];
cumulativeHistogram[values]++;
}
register int i;
float sum = 0.0f;
for(i=0; i<256; i++)
{
sum += cumulativeHistogram[i];
}
float mu = 0.0f;
float scale = 1.f/float(sum);
for(i=0; i<256; i++)
{
mu += float(i)*float(cumulativeHistogram[i]);
}
mu *= scale;
float mu1 = 0.0f;
float q1 = 0.0f;
float maxSigma = 0.0f;
int findThreshold = 0;
for(i=0; i<256; i++)
{
float pI, q2, mu2, sigma;
pI = float(cumulativeHistogram[i])*scale;
mu1 *= q1;
q1 += pI;
q2 = 1.f - q1;
if( min(q1, q2) < FLT_EPSILON || max(q1, q2) > 1.f - FLT_EPSILON )
{
continue;
}
mu1 = (mu1 + i*pI)/q1;
mu2 = (mu - q1*mu1)/q2;
sigma = q1*q2*(mu1-mu2)*(mu1-mu2);
if(sigma > maxSigma)
{
maxSigma = sigma;
findThreshold = i;
}
}
return findThreshold;
}
void RunFixedThresholding(unsigned char* srcImage, unsigned char* binaryImage, const int imageWidth, const int imageHeight, int threshold)
{
register int k;
int totalPixelNum = imageWidth*imageHeight;
for(k=0; k<totalPixelNum; k++)
{
binaryImage[k] = (srcImage[k] > threshold) ? OBJECT : BACKGROUND;
}
}