OpenCV2.4-使用P参数法二值化

二值化是图像处理的基本操作,OpenCV提供了:

固定阈值二值化.

--threshold(... ...,CV_THRESH_BINARY);

最大类间方差法(大津法OTSU)二值化.

--threshold(... ...,CV_THRESH_OTSU);

局部自适应二值化.

--adaptiveThreshold(... ...);

除以上方法外,P参数法(按照预定的模式亮度占比二值化),也是实用的二值化方法,OpenCV没有提供,可以自己封装.

#include <opencv2/opencv.hpp> 
#include <iostream>

using namespace std;
using namespace cv;

/*
	C_FUNC:pValueThreshold
	功能	:p参数法,将Mat图像二值化,并输出.
	参数:
		Frame:输入图像
		maxValue:预估目标范围的最大值比例,取值[0~255]
		ratio:p参数占比
		valueTop:二值化后亮度区的取值
	返回:成功返回0,不满足条件返回-1
	附注:
		maxValue不是亮度取值,而是亮度比例,要将亮度映射到[0~255]区间.
		输入的图像会被二值化,如果要保存原图,请复制后再处理.
*/

int pValueThreshold(Mat Frame, int maxValue, double ratio, int valueTop)
{
	//直方图均衡化
	equalizeHist(Frame, Frame);

	//计算直方图
	Mat hist;				//将要获得的直方图
	int imgNum = 1;			//图像数量
	int histDim = 1;			//直方图维度
	int histSize = 256;			//每个维度的bin个数
	float range[] = { 0,256 };	//每个维度的统计范围
	const float* histRange = { range };
	bool accumulate = false;
	calcHist(&Frame, 1, 0, Mat(), hist, 1, &histSize, &histRange, true, false);

	//hist中的第一行,是直方图的值.
	float* p = hist.ptr<float>(0);

	//循环计算阈值
	int countPix = Frame.cols * Frame.rows;
	int thresholdPix = 0;
	double ratioReal;
	int thresholdValue = maxValue;
	for (; thresholdValue >= 0; thresholdValue--)
	{
		thresholdPix += p[thresholdValue];
		ratioReal = (double)thresholdPix / countPix;
		if (ratioReal>ratio)
		{
			break;
		}
	}

	//可能图像不符合要求
	if (thresholdValue < 0)
	{
		return -1;
	}

	//使用阈值将图像二值化
	int curValue = 0;
	for (int i = 0; i < Frame.rows; ++i)
	{
		for (int j = 0; j < Frame.cols; ++j)
		{
			curValue = Frame.at<uchar>(i, j);
			if (curValue >= thresholdValue && curValue <= maxValue)
			{
				Frame.at<uchar>(i, j) = valueTop;
			}
			else
			{
				Frame.at<uchar>(i, j) = 0;
			}
		}
	}
	return 0;
}

int main(int argc, char* argv[])
{
	//读取灰度图像
	Mat src = imread("F:/Bar/晶粒模板/F31.bmp", 0);
	if (src.empty())
	{
		cout << "no such file or dictionary!" << endl;
		return -1;
	}

	//拷贝图像
	Mat dst = src.clone();

	//二值化
	int res = pValueThreshold(dst, 240, 0.26346, 255);
	if (-1 == res)
	{
		cout << "ERROR: pValueThreshold" << endl;
	}

	//显示图像
	imshow("gray", src);
	imshow("binary", dst);

	//等待按键
	waitKey(0);

	return 0;
}

猜你喜欢

转载自blog.csdn.net/csm1972385274/article/details/80029314
今日推荐