본문 바로가기

Image Processing/Image Binarization

[구현(c)/1979] A threshold selection method from gray level histograms

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;
	}

}