opencv图像处理学习(六十二)——寻找波峰与获取最佳阈值

1.寻找波峰

原理后面再补,先上代码:

cv::Mat findpeakmax(cv::Mat srcImage, std::vector& resultVec)//求波峰
{
	cv::Mat value;//返回投影向量

	cv::Mat VerMat;
	cv::Mat resMat = srcImage.clone();

	//阈值化操作
	int thresh = 130;
	int threshType = 0;
	//预设最大值
	const int maxVal = 255;
	//固定阈值化操作
	cv::threshold(srcImage, srcImage, thresh, maxVal, threshType);
	srcImage.convertTo(srcImage, CV_32FC1);
	//计算垂直投影
	cv::reduce(srcImage, VerMat, 0, CV_REDUCE_SUM);
	//遍历求差分符号
	float *iptr = ((float*)VerMat.data) + 1;
	std::vector tempVec(VerMat.cols - 1, 0);

	for (int i = 1; i < VerMat.cols - 1; ++i, ++iptr)
	{
		if (*(iptr + 1) - *iptr > 0)
		{
			tempVec[i] = 1;
		}

		else if (*(iptr + 1) - *iptr < 0)
		{
			tempVec[i] = -1;
		}

		else
		{
			tempVec[i] = 0;
		}
	}
	//对符号函数进行遍历
	for (int i = tempVec.size() - 1; i >= 0; i--)
	{
		if (tempVec[i] == 0 && tempVec.size() - 1)
		{
			tempVec[i] = 1;
		}

		else if (tempVec[i] == 0)
		{
			if (tempVec[i + 1] >= 0)
			{
				tempVec[i] = 1;
			}

			else
			{
				tempVec[i] = -1;
			}
		}
	}

	//波峰判断输出
	for (std::vector::size_type i = 0; i != tempVec.size() - 1; i++)
	{
		if (tempVec[i + 1] - tempVec[i] == -2)//+2为波谷
		{
			resultVec.push_back(i + 1);
		}
	}

	//输出波峰位置
	for (int i = 0; i < resultVec.size(); i++)
	{
		for (int ii = 0; ii < resMat.rows; ++ii)
		{
			resMat.at(ii, resultVec[i]) = 255;
		}
	}

	value = VerMat;
	return value;
}

2.寻找最佳阈值:

原理后面再补,先上代码:

#pragma region 寻找最佳阈值函数-Get_IterationThres
int Get_IterationThres(cv::Mat Img)
{
	/************************绘制直方图****************************/
	const int channels[1] = { 0 };
	//直方图的每一个维度的 柱条的数目(就是将灰度级分组)  
	int histSize[] = { 256 };   //如果这里写成int histSize = 256;   那么下面调用计算直方图的函数的时候,该变量需要写 &histSize  
								//定义一个变量用来存储 单个维度 的数值的取值范围    
	float midRanges[] = { 0, 256 };
	//确定每个维度的取值范围,就是横坐标的总数    
	const float *ranges[] = { midRanges };
	//输出的结果存储的 空间 ,用MatND类型来存储结果  
	cv::MatND dstHist;
	double* HistGram = new double[256];
	calcHist(&Img, 1, channels, cv::Mat(), dstHist, 1, histSize, ranges, true, false);
	for (int i = 0; i < 256; i++)
	{
		HistGram[i] = dstHist.at(i);
	}
	int X, Iter = 0;
	int MeanValueOne, MeanValueTwo, SumOne, SumTwo, SumIntegralOne, SumIntegralTwo;
	int MinValue, MaxValue;
	int NewThreshold;

	for (MinValue = 0; MinValue < 256 && HistGram[MinValue] == 0; MinValue++);
	{
		for (MaxValue = 255; MaxValue > MinValue && HistGram[MinValue] == 0; MaxValue--);
		{
			if (MaxValue == MinValue)
				return MaxValue;          // 图像中只有一个颜色             
			if (MinValue + 1 == MaxValue)
				return MinValue;      // 图像中只有二个颜色
		}
	}
	int IterationThres = MinValue;
	NewThreshold = (MaxValue + MinValue) >> 1;//NewThreshold为灰度最大最小值的平均值
	while (IterationThres != NewThreshold)//当前后两次迭代获得阈值相同时,结束迭代    
	{
		SumOne = 0;
		SumIntegralOne = 0;
		SumTwo = 0;
		SumIntegralTwo = 0;
		IterationThres = NewThreshold;
		for (X = MinValue; X <= IterationThres; X++)//根据阈值将图像分割成目标和背景两部分,求出两部分的平均灰度值      
		{
			SumIntegralOne += HistGram[X] * X;
			SumOne += HistGram[X];
		}
		MeanValueOne = SumIntegralOne / SumOne;
		for (X = IterationThres + 1; X <= MaxValue; X++)
		{
			SumIntegralTwo += HistGram[X] * X;
			SumTwo += HistGram[X];
		}
		if (SumTwo == 0)
		{
			NewThreshold = MeanValueOne;
		}
		else
		{
			MeanValueTwo = SumIntegralTwo / SumTwo;
			NewThreshold = (MeanValueOne + MeanValueTwo) >> 1;//求出新的阈值
		}
		Iter++;
		if (Iter >= 1000)
			return -1;
	}
	return IterationThres;
}

 

你可能感兴趣的:(学习opencv)