大津阈值法原理_ostu阈值分割

大津阈值法原理_ostu阈值分割具体的公式推导参见冈萨雷斯**《数字图像处理》**Otsu方法又称最大类间方差法,通过把像素分配像素分为两类或多类,计算类间方差,当方差达到最大值时,类分割线(即灰度值)就作为图像分割阈值。Otsu还有一个重要的性质,即它完全基于对图像直方图进行计算,这也使他成为最常用的阈值处理算法之一。算法步骤如下:…

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE使用 1年只要46元 售后保障 童叟无欺

具体的公式推导参见冈萨雷斯 《数字图像处理》

Otsu方法又称最大类间方差法,通过把像素分配为两类或多类,计算类间方差,当方差达到最大值时,类分割线(即灰度值)就作为图像分割阈值。Otsu还有一个重要的性质,即它完全基于对图像直方图进行计算,这也使他成为最常用的阈值处理算法之一。

算法步骤如下:
在这里插入图片描述
Otsu只有在直方图呈现双峰的时候才会有一个很好的效果,在直方图单峰或多峰的情况下效果不是很好,那就需要通过实际情况来选取其他的方法来得到预期的分割效果。

代码如下;

//返回阈值的大津阈值法
double Otsu_threshold(const cv::Mat& InputImage)
{ 
   	
	cv::Mat SrcImage = InputImage.clone();
	CV_Assert(SrcImage.type() == CV_8UC1);

	int rows = SrcImage.rows;
	int cols = SrcImage.cols;

	const int L = 256;
	int N = rows * cols;					//灰度图大小(元素个数)
	int n_i[L] = { 
    0 };						//灰度直方图
	
	for (int i = 0; i < rows; ++i)
	{ 
   
		uchar* p = SrcImage.ptr<uchar>(i);
		for (int j = 0; j < cols; ++j)
			n_i[p[j]]++;
	}

	double pn_i[L];							//概率灰度直方图
	for (int i = 0; i < L; ++i)
	{ 
   
		pn_i[i] = (double)n_i[i] / N;
	}

	//全局均值和全局方差
	cv::Mat mat_mean, mat_stddev;
	double gray_mean, gray_sigma;

	cv::meanStdDev(SrcImage, mat_mean, mat_stddev);
	gray_mean = mat_mean.at<double>(0, 0);			//m_G
	//全局方差是用来计算类的可分离测度
	gray_sigma = mat_stddev.at<double>(0, 0) * mat_stddev.at<double>(0, 0);

	//遍历所有灰度级,计算类间方差
	std::vector<double>sigma_ks(L);
	for (int k = 0; k < L; ++k)
	{ 
   
		double p1 = 0.0;				//p1类发生概率
		double m_k = 0.0;				//高达k阶累计平均灰度

		for (int i = 0; i <= k; ++i)
		{ 
   
			p1 += pn_i[i];
			m_k += i * pn_i[i];
		}

		if (p1 == 0.0 || (1 - p1) == 0.0)					//分母不能为0
			sigma_ks[k] = 0.0;
		else
			sigma_ks[k] = (gray_mean * p1 - m_k) * (gray_mean * p1 - m_k) / (p1 * (1 - p1));
	}

	double max_Sigma_k = 0.0;
	std::vector<int>maxval_Ts;
	double Threshold_T = 0;									//最终输出的阈值T
	//找类间方差最大值
	for (int i = 0; i < sigma_ks.size(); ++i)
	{ 
   
		if (sigma_ks[i] > max_Sigma_k)
			max_Sigma_k = sigma_ks[i];
	}
	//找极大值对应的所有灰度值
	for (int i = 0; i < sigma_ks.size(); ++i)
	{ 
   
		if (abs(max_Sigma_k - sigma_ks[i]) < 1e-8)
			maxval_Ts.push_back(i);
	}
	//如果极大值点不唯一,那么取对应各个极大值的各个k的平均值来得到最终阈值threshold_T
	for (int i = 0; i < maxval_Ts.size(); ++i)
		Threshold_T += maxval_Ts[i];

	return Threshold_T / maxval_Ts.size();
}

//-----------------test--------------------//
int main()
{ 
   
	std::string path = "F:\\NoteImage\\Lena.jpg";
	cv::Mat src = imread(path, cv::IMREAD_GRAYSCALE);
	if (!src.data) { 
   
		std::cout << "Could not open or find the image" << std::endl;
		return -1;
	}

	cv::Mat dst;
	//对比一下opencv官方计算结果(显然结果是相同的)
	double thres1 = cv::threshold(src, dst, 0, 255, cv::THRESH_OTSU);
	double thres2 = Otsu_threshold(src);

	std::cout << "opencv = " << thres1 << " my = " << thres2;

	cv::waitKey(0);
	return 0;
}

处理结果:

在这里插入图片描述


与本博文有关的其他博文:
mask_otsu

自适应阈值Canny

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/184852.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 配置监听_1521端口占用问题

    配置监听_1521端口占用问题声明:原创作品,出自“深蓝的blog”博客,欢迎转载,转载时请务必注明出处,否则追究版权法律责任。深蓝的blog: 前提回现修改了主机名,由hyldb修改为hyl。问题现象配置监听,警告提示,如下所示:解决方法1、检查1521端口[root@hyl~]#netstat-a–查看端口占用情况,查明1521端口并未被占用ActiveInte

    2022年6月5日
    43
  • drupal教程 Drupal的电子商务模块(ecommerce module)[通俗易懂]

    drupal教程 Drupal的电子商务模块(ecommerce module)[通俗易懂]译者:老葛Drupal自身并没有自带一个电子商务模块,但是开发者贡献了一个电子商务模块E-commercemodule。事实上,还有一个模块ubercartmodule,后者看起来功能更强大一些,而且后者有专门的论坛和开发者。但是我还是选择了前者,这个更简单一些的ecommercemodule。原因很简单,与电子商务相关的是支付功能,对于前者来说,存在着大量的各个支付网管的模块功

    2022年6月1日
    71
  • linux下解压rar压缩文件

    linux下解压rar压缩文件在windows下我们压缩解压文件通常后缀为rar,在linux下我们压缩解压文件通常后缀为tar默认在linux下我们不能解压压缩rar文件我们可以下载rarlinux安装包实现解压压缩后缀为rar的包下载地址:WinRARarchiver,apowerfultooltoprocessRARandZIPfiles安装~]#wgethttps://www.rarlab.com/rar/rarlinux-x64-610.tar.gz~]#tar-zxv.

    2022年7月11日
    14
  • Linux下PyTorch、CUDA Toolkit 及显卡驱动版本对应关系(附详细安装步骤)

    Linux下PyTorch、CUDA Toolkit 及显卡驱动版本对应关系(附详细安装步骤)Linux下PyTorch、CUDAToolkit及显卡驱动版本对应关系(附详细安装步骤)

    2022年6月16日
    290
  • rabitmq,redis以及kafuka作为消息队列的区别[通俗易懂]

    rabitmq,redis以及kafuka作为消息队列的区别[通俗易懂]kafukakafuka涉及到的名词词意解释:Kafka作为时下最流行的开源消息系统,被广泛地应用在数据缓冲、异步通信、汇集日志、系统解耦等方面。相比较于RocketMQ等其他常见消息系统,Kafka在保障了大部分功能特性的同时,还提供了超一流的读写性能。针对Kafka性能方面进行简单分析,相关数据请参考:https://segmentfault.com/a/119000000398…

    2022年4月30日
    53
  • docker 搭建drone + gitee 的CI/CD

    docker 搭建drone + gitee 的CI/CD准备创建OAuth应用程序创建一个GiteeOAuth应用程序。ConsumerKey和ConsumerSecret用于授权访问Gitee资源。授权回调URL必须与以下格式和路径匹配,并且必须使用您的确切服务器方案和主机。创建共享密钥创建一个共享密钥来验证跑步者和您的中央无人机服务器之间的通信。您可以使用openssl生成共享密钥:$opensslrand-hex16bea26a2221fd8090ea38720fc445ec.

    2022年8月15日
    17

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号