opencv 中的Otsu阈值化

本文详细介绍OTSU阈值法的原理与实现过程,通过计算类间方差最大化确定最佳阈值,适用于图像二值化处理。文中提供了一个完整的C++实现示例,包括灰度图像的读取、直方图统计、类间方差计算及阈值选择。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

参考数字图像处理(三)  Pg 480


Otsu 方法的处理:选取合适的阈值k,使得类间方差最大P1*(m1-mg)*(m1-mg)+ P2*(m2-mg)*(m1-mg)最大

P1为像素分到C1的概率,即C1类像素占全部像素的比例,

P1为像素分到C2的概率,即C2类像素占全部像素的比例,

 m1位C1类像素的平均灰度,计算公式 (0*n0 + 1*n1 +2*n2 ...k*nk ) /  (n0 + n1 +n2 ...nk)      其中ni 表示灰度值为i像素的个数 。


代码如下:

<span style="font-size:18px;">//otsu          选取合适的阈值k,使得类间方差最大P1(m1-mg)平方 + P2(m2-mg)平方,k从0-255之间遍历,选取最合适的
  //P1为像素分到C1的概率,即C1类像素占全部像素的比例,计算公式(n0 +n1 + n2 +...nk)/ (size总像素点数)。 m1位C1类像素的平均灰度,计算公式 (0*n0 + 1*n1 +2*n2 ...k*nk ) /  (n0 + n1 +n2 ...nk)    *****ni 表示各像素的个数 直方图
//  mg为总的像素平均灰度值
int otsu_threshold( Mat gray)
{
	int img_width ;
	int img_height;
	int size;  
	float P1 ,P2;
	float m1=0, m2=0 , mg=0;
	int k_otsu;  //最终找到的阈值
	float deltaTmp=0,deltaMax=0;  //类间方差
	int n0_k = 0;   //即(n0 +n1 + n2 +...nk)
	int nk_255 = 0;

	int nk_X_k =0;  //   表示(0*n0 + 1*n1 +2*n2 ...k*nk )
	int nk_X_k2 =0;  //  表示

	
	int pixel_count[256];   //存储0-255每个像素的个数 即ni
	img_width = gray.cols;
	img_height = gray.rows;
	size = img_width * img_height;
	
	
	for(int i=0; i<256; i++)
	{
		pixel_count[i] = 0;
	}
	 
		//归一化直方图,统计每个像素点个数   即pi
	for(int i=0 ; i<img_height; i++)
	{
		for( int j= 0; j<img_width; j++)
		{
			 pixel_count[ gray.at<unsigned char>(i,j)]++;
		}
	
	}

	//计算mg  , mg为总的像素平均灰度值
	for (int i= 0; i<256; i++)
	{
		mg += pixel_count[i] *i;
	}
	mg = mg /size;

	for (int k=1; k<256; k++)    //类间方差统计  阈值k从0-255,筛选出最大方差的k
	{
		n0_k = 0;
		nk_X_k = 0;
		nk_X_k2 = 0;
	 
		for (int i=0; i<=k ; i++)
		{
			n0_k += pixel_count[i];     //   P1 = n0_k  / size

			nk_X_k += pixel_count[i] *i;  // m1 = nk_X_k / n0_k
		
		}
		for (int j=k+1; j<256; j++)   //计算m2
		{
			nk_X_k2 += pixel_count[j]*j;
		
		}


		P1 = n0_k  /(float) size;
		m1 = nk_X_k / n0_k;
		P2 = 1-P1;
		m2 = nk_X_k2 / (float)(size - n0_k);    


		deltaTmp = P1*(m1-mg)*(m1-mg) + P2*(m2-mg)*(m2-mg);  //类间方差
		if(deltaTmp > deltaMax)
		{
			deltaMax = deltaTmp;
			k_otsu = k;
		}		
		
	}
	return k_otsu;


}


int main()
{
	Mat origin_img, gray, result;
	int k;
	origin_img = imread("C://Users/Administrator/Desktop/车牌/2.jpg");
	cvtColor(origin_img,gray,CV_BGR2GRAY);  //灰度化

	k = otsu_threshold(gray);

	threshold(gray,result,k,255,CV_THRESH_BINARY);  //阈值化得到二值图
	namedWindow("result",WINDOW_NORMAL );  

	imshow("result",result);
	waitKey(0);



}</span>


评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值