영상처리

AutoThreshold (IJDefault) C++

park__ 2024. 12. 10. 17:01

Java -> C++ 로 변경

 

Code

int IJDefault(float* histo, int n_length) 
{
	// Original IJ implementation for compatibility.
	int level;
	int maxValue = n_length - 1;
	double result, sum1, sum2, sum3, sum4;

	int min = 0;
	while ((histo[min] == 0) && (min < maxValue))
		min++;

	int max = maxValue;

	while ((histo[max] == 0) && (max > 0))
		max--;

	if (min >= max) 
	{
		level = n_length / 2;
		return level;
	}

	int movingIndex = min;
	int inc = std::max(max / 40, 1);

	do 
	{
		sum1 = sum2 = sum3 = sum4 = 0.0;

		for (int i = min; i <= movingIndex; i++) 
		{
			sum1 += i * histo[i];
			sum2 += histo[i];
		}

		for (int i = (movingIndex + 1); i <= max; i++) 
		{
			sum3 += i * histo[i];
			sum4 += histo[i];
		}

		result = (sum1 / sum2 + sum3 / sum4) / 2.0;
		movingIndex++;

	} while ((movingIndex + 1) <= result && movingIndex < max - 1);

	//.showProgress(1.0);
	level = (int)round(result);
	return level;
}

 

사용 예시

		std::string str_image_path;
		cv::Mat raw_img = cv::imread(str_image_path, -1);
		cv::Mat raw_img_8bit;
		
		// 8Bit 1Channel 만 가능...
		raw_img.convertTo(raw_img_8bit, CV_8UC1, 256.0 / 65536.0);

		int histSize = 256;    
		float range[] = { 0, 255 };
		const float* histRange = { range };
		cv::Mat hist;
		cv::calcHist(&raw_img_8bit, 1, 0, cv::Mat(), hist, 1, &histSize, &histRange);

		int n_length = raw_img.rows * raw_img.cols;
		uint8_t threshold_value = IJDefault((float*)hist.data, 256);
	
		cv::Mat threshold_img;
		cv::threshold(raw_img_8bit, threshold_img, threshold_value, 255, cv::THRESH_BINARY);

 

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