영상처리

AutoThreshold (Minimum) C++

park__ 2024. 12. 11. 11:28

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 Minimum(float* histo, int n_length)
{
	if (n_length < 2)
		return 0;
	// 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.
	// Threshold t is such that yt-1 > yt ≤ yt+1.
	// Images with histograms having extremely unequal peaks or a broad and
	// flat valley are unsuitable for this method.
	int iter = 0;
	int threshold = -1;
	int max = -1;
	double* iHisto = nullptr; 
	double* tHisto = nullptr; 
	
	iHisto = new double[n_length];
	tHisto = new double[n_length]; // Instead of double[] tHisto = iHisto ;

	for (int i = 0; i < n_length; i++) 
	{
		iHisto[i] = (double)histo[i];
		
		if (histo[i] > 0) 
			max = i;
	}
		
	while (!bimodalTest(iHisto, n_length))
	{
		//smooth with a 3 point running mean filter
		for (int i = 1; i < n_length - 1; i++)
			tHisto[i] = (iHisto[i - 1] + iHisto[i] + iHisto[i + 1]) / 3;
		
		tHisto[0] = (iHisto[0] + iHisto[1]) / 3; //0 outside
		tHisto[n_length - 1] = (iHisto[n_length - 2] + iHisto[n_length - 1]) / 3; //0 outside
		std::memcpy(iHisto, tHisto, n_length * sizeof(double)); //Instead of iHisto = tHisto ;
		iter++;

		if (iter > 10000) 
		{
			threshold = -1;
			std::cout << ("Minimum Threshold not found after 10000 iterations.");
			return threshold;
		}
	}
	// The threshold is the minimum between the two peaks. modified for 16 bits

	for (int i = 1; i < max; i++)
	{
		//IJ.log(" "+i+"  "+iHisto[i]);
		if (iHisto[i - 1] > iHisto[i] && iHisto[i + 1] >= iHisto[i])
		{
			threshold = i;
			break;
		}
	}

	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