OpenCV - OTSU二值化分割

其实OpenCV中内置了这个二值化算法,在Threshold方法中

double threshold( InputArray src, OutputArray dst, double thresh, double maxval, int type );
/*
阈值类型有如下几种:
		0:二进制阈值化--THRESH_BINARY
		1:反二进制阈值化--THRESH_BINARY_INV
		2:截断阈值化:大于该阈值的像素点被设定为该阈值--THRESH_TRUNC
		3:阈值化为0:低于阈值被设置为0--THRESH_TOZERO
		4:反阈值化为0:超过阈值被设置为0--THRESH_TOZERO_INV
		8:OTSU阈值化--CV_THRESH_OTSU
*/

参数说明:
第一个参数:InputArray类型的src,输入数组,填单通道,8位或32位浮点类型Mat即可。即为输入图像。
第二个参数:函数运算后的结果存放在这。即为输出图像(与输入图像同样的尺寸和类型)。
第三个参数:double类型的thresh,阈值的具体值。根据需要自行设置。
第四个参数:表示预设最大值,使用THRESH_BINARY或THRESH_BINARY_INV类型。
第五个参数:int类型的type,表示阈值化处理的类型。
 


otsu的c++实现,需要参考公式 :https://blog.csdn.net/liuzhuomei0911/article/details/51440305

效果如下:

OpenCV - OTSU二值化分割_第1张图片

#include "pch.h"
#include 
#include 

int OTSU(cv::Mat& img);

int main()
{
	cv::Mat src = cv::imread("lena.png", 0);
	cv::imshow("src", src);
	int threshold = OTSU(src);
	cv::Mat dst(src.size(), CV_8UC1);
	for (int i = 0; i < dst.rows; i++)
	{
		for (int j = 0; j < dst.cols; j++)
		{
			//阈值判断。 若该点值大于阈值,则设为255,否则设为0。
			if (src.at(i, j) > threshold)
				dst.at(i, j) = 255;
			else
				dst.at(i, j) = 0;
		}
	}
	cv::imshow("otsu", dst);
	cv::waitKey(0);
}

int OTSU(cv::Mat& img)
{
	int nRows = img.rows;
	int nCols = img.cols;
	int threshold = 0;

	int nSumPix[256];
	float nProDis[256];

	for (int i = 0; i < nRows; i++)
	{
		for (int j = 0; j < nCols; j++)
		{
			nSumPix[(int)img.at(i, j)]++;
		}
	}

	for (int i = 0; i < 256; i++)
	{
		nProDis[i] = (float)nSumPix[i] / (nCols*nRows);
	}

	float wb, wf; //比重. wb-背景部分; wf-前景部分
	float u0_temp, u1_temp, u0, u1;	//平均值
	float delta_temp;	//存放临时方差
	double delta_max = 0.0;	//初始化最大类间方差
	for (int i = 0; i < 256; i++)
	{
		wb = wf = u0_temp = u1_temp = u0 = u1 = delta_temp = 0;//初始化相关参数
		for (int j = 0; j < 256; j++)
		{
			//背景部分
			if (j <= i)
			{
				//当前i为分割阈值,第一类总的概率
				wb += nProDis[j];	//比重
				u0_temp += j * nProDis[j];
			}
			//前景部分
			else
			{
				//当前i为分割阈值,第一类总的概率
				wf += nProDis[i];	//比重
				u1_temp += j * nProDis[j];
			}
		}
		//------------分别计算各类的平均值------------
		u0 = u0_temp / wb;
		u1 = u1_temp / wf;
		//-----------计算最大类间方差------------
		delta_temp = (float)(wb*wf*pow((u0 - u1), 2));//形如pow(x,y);其作用是计算x的y次方。
		//------------依次找到最大类间方差下的阈值------------
		if (delta_temp > delta_max)
		{
			delta_max = delta_temp;
			threshold = i;
		}
	}//计算结束
	return threshold;	//返回OTUS计算出的阈值


}

 

你可能感兴趣的:(OpenCV)