영상처리

AutoThreshold (MaxEntropy) C++

park__ 2024. 12. 11. 10:35

Java -> C++

 

Code

int MaxEntropy(float* histo, int n_length) {
	// Implements Kapur-Sahoo-Wong (Maximum Entropy) thresholding method
	// Kapur J.N., Sahoo P.K., and Wong A.K.C. (1985) "A New Method for
	// Gray-Level Picture Thresholding Using the Entropy of the Histogram"
	// Graphical Models and Image Processing, 29(3): 273-285
	// M. Emre Celebi
	// 06.15.2007
	// Ported to ImageJ plugin by G.Landini from E Celebi's fourier_0.8 routines
	int threshold = -1;
	int ih, it;
	int first_bin;
	int last_bin;
	double tot_ent;  /* total entropy */
	double max_ent;  /* max entropy */
	double ent_back; /* entropy of the background pixels at a given threshold */
	double ent_obj;  /* entropy of the object pixels at a given threshold */
	int total = 0;
	double* norm_histo = nullptr; /* normalized histogram */
	double* P1 = nullptr; /* cumulative normalized histogram */
	double* P2 = nullptr;

	norm_histo = new double[n_length]; 
	P1 = new double[n_length];
	P2 = new double[n_length];

	for (ih = 0; ih < n_length; ih++)
		total += histo[ih];

	for (ih = 0; ih < n_length; ih++)
		norm_histo[ih] = (double)histo[ih] / total;

	P1[0] = norm_histo[0];
	P2[0] = 1.0 - P1[0];

	for (ih = 1; ih < n_length; ih++) 
	{
		P1[ih] = P1[ih - 1] + norm_histo[ih];
		P2[ih] = 1.0 - P1[ih];
	}

	/* Determine the first non-zero bin */
	first_bin = 0;

	for (ih = 0; ih < n_length; ih++) 
	{
		if (!(abs(P1[ih]) < 2.220446049250313E-16)) 
		{
			first_bin = ih;
			break;
		}
	}

	/* Determine the last non-zero bin */
	last_bin = n_length - 1;

	for (ih = n_length - 1; ih >= first_bin; ih--) 
	{
		if (!(abs(P2[ih]) < 2.220446049250313E-16)) 
		{
			last_bin = ih;
			break;
		}
	}

	// Calculate the total entropy each gray-level
	// and find the threshold that maximizes it 
	max_ent = -DBL_MAX;

	for (it = first_bin; it <= last_bin; it++) 
	{
		/* Entropy of the background pixels */
		ent_back = 0.0;

		for (ih = 0; ih <= it; ih++) 
		{
			if (histo[ih] != 0) 
			{
				ent_back -= (norm_histo[ih] / P1[it]) * log(norm_histo[ih] / P1[it]);
			}
		}

		/* Entropy of the object pixels */
		ent_obj = 0.0;

		for (ih = it + 1; ih < n_length; ih++)
		{
			if (histo[ih] != 0) 
			{
				ent_obj -= (norm_histo[ih] / P2[it]) * log(norm_histo[ih] / P2[it]);
			}
		}

		/* Total entropy */
		tot_ent = ent_back + ent_obj;

		// IJ.log(""+max_ent+"  "+tot_ent);
		if (max_ent < tot_ent) 
		{
			max_ent = tot_ent;
			threshold = it;
		}
	}

	if (norm_histo)
		delete[] norm_histo;

	if (P1)
		delete[] P1;

	if (P2)
		delete[] P2;

	return threshold;
}

 

imageJ 관련 문서 : https://imagej.net/plugins/auto-threshold

github link : https://github.com/fiji/Auto_Threshold/blob/master/src/main/java/fiji/threshold/Auto_Threshold.java

'영상처리' 카테고리의 다른 글

AutoThreshold (MinErrorI) C++  (0) 2024.12.11
AutoThreshold (Mean) C++  (0) 2024.12.11
OpenCV convertTo (16bit -> 8bit)  (0) 2024.12.11
AutoThreshold (Intermodes) C++  (0) 2024.12.11
AutoThreshold (IJDefault) C++  (0) 2024.12.10