自己实现图像阈值化(OTSU)

自己实现图像阈值化(OTSU)
OTSU代码:

#include <opencv2/opencv.hpp>
#include <iostream>
using namespace std;
using namespace cv;

void OtusThreshold(Mat &src,Mat &dst)
{
	dst=src.clone();		// 原图数据区指针
	uchar* p_data=dst.data;
	
	int nLineByte =dst.cols;	// 图像每行像素所占的字节数
	int nWidth =dst.cols;		// 图像的宽度
	int nHeight =dst.rows;		// 图像的高度


	// 灰度直方图数组,并初始化
	int nGrayHistogram[256];
	memset(nGrayHistogram,0,sizeof(nGrayHistogram));

	// 统计各个灰度级对应的像素个数,并存放到灰度直方图数组中
	int nPixel;
	for (int j = 0; j < nHeight; j ++)
		for (int i = 0; i < nWidth; i ++)
		{
			// 获取当前像素点的灰度值
			nPixel = p_data[nLineByte * j + i];

			//对灰度值统计计数
			nGrayHistogram[nPixel] ++;
		}

	// c0组和c1组的均值
	float u0, u1;

	// c0组和c1组的概率
	float w0, w1;

	// c0组的像素总数
	int nCount0;

	// 阈值和最佳阈值(对应方差最大时的阈值)
	int nT, nBestT;

	// 方差和最大方差
	float fVaria, fMaxVaria = 0;

	// 统计直方图中像素点的总数,并存放到nSum中
	int nSum=0;
	for(int i = 0; i < 256; i ++)
	nSum += nGrayHistogram[i];



	// 令阈值nT从0遍历到255
	for(nT = 0; nT < 256; nT ++)
	{
		// 当阈值为nT时,计算c0组的均值和概率
		u0 = 0;
		nCount0 = 0;
		for(int i = 0; i <= nT; i++)
		{
			u0 += i * nGrayHistogram[i];
			nCount0 += nGrayHistogram[i];
		}
		u0 /= nCount0;
		w0 = (float) nCount0 / nSum;

		// 当阈值为nT时,计算c1组的均值和概率
		u1 = 0;
		for(int i = nT+1; i < 256; i ++)
			u1 += i * nGrayHistogram[i];
		u1 /= (nSum - nCount0);
		w1 = 1 - w0;

		// 计算两组间的方差
		fVaria = w0 * w1 * (u0 - u1) * (u0 - u1);

		// 记录最大方差和最佳阈值
		if(fVaria > fMaxVaria)
		{
			fMaxVaria = fVaria;
			nBestT = nT;
		}
	}

	// 利用最佳阈值对原图像作分割处理
	for(int j = 0; j < nHeight; j ++)
		for(int i = 0; i < nWidth; i ++)
		{
			if(p_data[j * nLineByte + i] < nBestT)
				p_data[j * nLineByte + i] = 0;
			else
				p_data[j * nLineByte + i] = 255;
		}
}
int main()
{
	Mat src=imread("E:\\51.jpg");
	Mat dst;
	Mat bin;
	cvtColor(src,dst,CV_BGR2GRAY);
	imshow("灰度图像",dst);
	OtusThreshold(dst,bin);
	imshow("灰度二值化",bin);
	imwrite("灰度图像的二值化.jpg",bin);
	waitKey(0);  
	return 0;  
}
运行结果:
        
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值