Otsu算法寻找灰度图像中最优分割阈值

1.Otsu算法介绍:

一幅大小为M*N像素的图像有L个不同的灰度级,用表示灰度级为i的像素数。则像素总数MN=,归一化直方图具有分量,故此有

假设有某个阈值k,可以将图像分为C0和C1两类,可理解为背景和前景。C0类像素灰度范围在[1,k],C1像素灰度范围为[k+1,L]。用该阈值,像素被划分到类C0中的概率和均值分别为:

,

u0中的Pr(i|C0)项是值i的概率,已知i来自C0类。根据贝叶斯公式:P(A/B)=P(B/A)P(A)/P(B),对于给定i的C0的概率P(C0|i)为1,因为我们只处理来自C0类的i值。同理,可得到C1类的概率和平均灰度值:

.,

其中有:

,

为了评价当阈值为k时的阈值效果,分别定义:

类间方差:

类内方差:

全局方差:

使用归一化的无量纲矩阵作为判断条件:

,

由类间方差可知,两个均值u1和u0彼此间隔越远,则类间方差的值越大,这表明类间方差时类之间的可分性度量。又因为全局方差是一个常数,由此可得出也是一个可分性度量,

且最大化这一度量相当于最大化类间方差。故Otsu算法的目标是确定阈值k,该阈值能最大化类间方差。

代码如下:

#include "opencv2/opencv.hpp"

using namespace cv;
int Otsu(Mat src);

int main()
{
	Mat img=imread("f://zhazha.jpg");
	imshow("img",img);

	Mat gray=Mat(img.rows,img.cols,CV_8UC1);
	cvtColor(img,gray,CV_RGB2GRAY);

	int thrld=Otsu(gray);

	threshold(gray,gray,thrld,255,THRESH_BINARY);

	imshow("thrld",gray);

	cvWaitKey(0);
	return 0;
}

int Otsu(Mat src)  
{  
	int height=src.rows;  
	int width=src.cols;      
	long size = height * width; 

	//histogram  
	float histogram[256] = {0};  
	for(int m=0; m < height; m++)
	{    
		for(int n = 0; n < width; n++) 
		{  
			int bgr=src.at(m,n);
			histogram[bgr]++;  
		}  
	}  

	int threshold;    
	long sum0 = 0, sum1 = 0; //存储前景的灰度总和和背景灰度总和
	long cnt0 = 0, cnt1 = 0; //前景的总个数和背景的总个数
	double w0 = 0, w1 = 0; //前景和背景所占整幅图像的比例
	double u0 = 0, u1 = 0;  //前景和背景的平均灰度
	double variance = 0; //最大类间方差
	int i, j;
	double u = 0;
	double maxVariance = 0;
	for(i = 1; i < 256; i++) //一次遍历每个像素
	{  
		sum0 = 0;
		sum1 = 0; 
		cnt0 = 0;
		cnt1 = 0;
		w0 = 0;
		w1 = 0;
		for(j = 0; j < i; j++)
		{
			cnt0 += histogram[j];
			sum0 += j * histogram[j];
		}

		u0 = (double)sum0 /  cnt0; 
		w0 = (double)cnt0 / size;

		for(j = i ; j <= 255; j++)
		{
			cnt1 += histogram[j];
			sum1 += j * histogram[j];
		}

		u1 = (double)sum1 / cnt1;
		w1 = 1 - w0; // (double)cnt1 / size;

		u = u0 * w0 + u1 * w1; //图像的平均灰度
		variance =  w0 * pow((u0 - u), 2) + w1 * pow((u1 - u), 2);//用类内方差求解最优阈值
		//variance =  w0 * w1 *  (u0 - u1) * (u0 - u1);//用类间方差求解最优阈值
		if(variance > maxVariance) 
		{  
			maxVariance = variance;  
			threshold = i;  
		} 
	}  
	return threshold;  
}  



你可能感兴趣的:(计算机视觉)