영상처리

AutoThreshold (Intermodes) C++

park__ 2024. 12. 11. 09:47

Java -> C++

 

Code

inline bool bimodalTest(double* y, int n_length) 
{
	int len = n_length;
	bool b = false;
	int modes = 0;

	for (int k = 1; k < len - 1; k++) 
	{
		if (y[k - 1] < y[k] && y[k + 1] < y[k]) 
		{
			modes++;

			if (modes > 2)
				return false;
		}
	}

	if (modes == 2)
		b = true;

	return b;
}

int Intermodes(float* histo, int n_length) 
{
	// J. M. S. Prewitt and M. L. Mendelsohn, "The analysis of cell images," in
	// Annals of the New York Academy of Sciences, vol. 128, pp. 1035-1053, 1966.
	// ported to ImageJ plugin by G.Landini from Antti Niemisto's Matlab code (GPL)
	// Original Matlab code Copyright (C) 2004 Antti Niemisto
	// See http://www.cs.tut.fi/~ant/histthresh/ for an excellent slide presentation
	// and the original Matlab code.
	//
	// Assumes a bimodal histogram. The histogram needs is smoothed (using a
	// running average of size 3, iteratively) until there are only two local maxima.
	// j and k
	// Threshold t is (j+k)/2.
	// Images with histograms having extremely unequal peaks or a broad and
	// flat valley are unsuitable for this method.
	
	double* iHisto = nullptr;
	iHisto = new double[n_length];
	
	int iter = 0;
	int threshold = -1;

	for (int i = 0; i < n_length; i++)
		iHisto[i] = (double)histo[i];

	while (!bimodalTest(iHisto, n_length)) {
		//smooth with a 3 point running mean filter
		double previous = 0, current = 0, next = iHisto[0];

		for (int i = 0; i < n_length - 1; i++) 
		{
			previous = current;
			current = next;
			next = iHisto[i + 1];
			iHisto[i] = (previous + current + next) / 3;
		}

		iHisto[n_length - 1] = (current + next) / 3;
		iter++;

		if (iter > 10000) 
		{
			threshold = -1;
			std::cout << "Intermodes Threshold not found after 10000 iterations.";

			return threshold;
		}
	}

	// The threshold is the mean between the two peaks.
	int tt = 0;
	for (int i = 1; i < n_length - 1; i++) 
	{
		if (iHisto[i - 1] < iHisto[i] && iHisto[i + 1] < iHisto[i]) 
		{
			tt += i;
			//IJ.log("mode:" +i);
		}
	}

	threshold = (int)floor(tt / 2.0);

	if (iHisto)
		delete[] iHisto;

	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