图像算法(三):自适应阈值化——OTSU()

最近在复习图像算法,对于一些简单的图像算法进行一个代码实现,由于找工作比较忙,具体原理后期补上,先上代码。今天先给出自适应阈值的代码,进行图像二值化。
(1)步骤:
(a)计算每个像素值的频数Hist
(b)计算每个像素值的频率(直方图)HistP = Hist/像素个数N
(c)计算累计直方图HistPSum
(d)均值=像素值*HistPSum,u,u1,u2
(e)权值w0 = HistPSum(k),w1= 1-w0;
(f)方差(u-u1)2和 (u-u0)2
(g)最大类间方差:w0 *(u-u0)2+w1 *(u-u1)2
(2)代码

#define _CRT_SECURE_NO_WARNINGS

# include 
# include   
# include

using namespace std;
using namespace cv;

Mat binary(Mat &gray, int threshold);
int cThreshold(Mat &gray);

int main()
{
	Mat srcImg = imread("D:\\Visual Studio 2015\\Girl.bmp");
	if (!srcImg.data)
	{
		cout << "图片不存在" << endl;
		return -1;
	}
	Mat srcGray;
	cvtColor(srcImg, srcGray, CV_RGB2GRAY);
	int threshold = cThreshold(srcGray);
	cout << threshold << endl;//输出阈值  
	Mat resultImg = binary(srcGray, threshold);
	imshow("gray", srcGray);
	imshow("result", resultImg);
	waitKey(0);
	return 0;
}

//二值化
Mat binary(Mat &gray, int threshold)
{
	int rows = gray.rows;
	int cols = gray.cols;
	Mat result = Mat::zeros(rows, cols, CV_8UC1);//这里一定记得要初始化
	int i, j;
	for (i = 0; i < rows; i++)
	{
		for (j = 0; j < cols; j++)
		{
			if (gray.at(i, j) > threshold)
			{
				result.at(i, j) = 255;
			}
			else
			{
				result.at(i, j) = 0;
			}
		}
	}
	return result;
}

//OSTU
int cThreshold(Mat &gray)
{
	int rows = gray.rows;
	int cols = gray.cols;
	int i, j;
	int threshold = 0;
	int Hist[256];
	double HistP[256];
	double HistPSum[256];
	double Average[256];
	double max = 0.0, wt, w0, w1, u, u0, u1;
	//初始化
	for (i = 0; i < 256; i++)
	{
		Hist[i] = 0;
		HistP[i] = 0.0;
		HistPSum[i] = 0.0;
		Average[i] = 0.0;
	}
	//统计频数
	for (i = 0; i < rows; i++)
	{
		for (j = 0; j < cols; j++)
		{
			Hist[(int)gray.at(i, j)]++; //int很重要
		}
	}
	//统计直方图
	for (i = 0; i < 256; i++)
	{
		HistP[i] = (double)Hist[i] / (rows*cols);
	}
	//累计直方图及均值
	HistPSum[0] = HistP[0];
	Average[0] = 0.0;
	for (i = 1; i < 256; i++)
	{
		HistPSum[i] = HistPSum[i - 1] + HistP[i];
		Average[i] = Average[i - 1] + (double)i*HistP[i];
	}

	u = Average[255];
	for (i = 1; i < 256; i++)
	{
		w0 = HistPSum[i];
		w1 = 1 - w0;
		u0 = Average[i];
		if (fabs(w0) > 0.001 && fabs(w1) > 0.001)
		{
			u1 = (u - w0 * u0) / w1;
			wt = (double)w0* pow((u - u0), 2) + w1* pow((u - u1), 2);
			if (wt > max)
			{
				max = wt;
				threshold = i;
			}
		}
	}
	return threshold;
}

(3)结果
图像算法(三):自适应阈值化——OTSU()_第1张图片
推荐参考博客:https://me.csdn.net/linqianbi

你可能感兴趣的:(opencv,c++,计算机视觉,图像处理,算法)