大津阈值法原理_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)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 操作系统概念第五章部分作业题答案

    操作系统概念第五章部分作业题答案题目一:为什么对调度程序而言,区分CPU约束性进程和I/O约束性进程很重要解答:绝大多数进程可分为I/O主(放入I/O队列)或CPU主(放入就绪队列),I/O主的计算时间>CPU主。因此长期调度程序应选择一个合理的包含I/O主和CPU主的组合进程。在运行I/O操作前,I/0限制的程序只运行很少数量的计算机操作。而CPU约束程序一般来使用很多的CPU。另一方面,CPU约束程序会利用整个时间片,…

    2022年7月14日
    11
  • 函数模版特化(类模板的实例化在什么阶段)

    本文转自:https://www.cnblogs.com/dracohan/p/3401660.html 转来收藏以便查阅,感谢原作者今天在写代码时,遇到了模板和特化,在网上找了资料后问题呗一一解决,转载此文用于以后查阅,感谢原创者。其中增加了我自己的总结:特化函数与模板函数的区别:(1)、模板函数的T参数只能传入类类型的参数;特化函数的参数只能传入对应的参数类型,基本类型或类类型。…

    2022年4月17日
    64
  • SpringBootTest 和PowerMocker

    SpringBootTest 和PowerMockerimportstaticorg.junit.Assert.assertNotEquals;importstaticorg.junit.Assert.assertNotNull;importstaticorg.junit.Assert.assertTrue;importjava.util.HashMap;importjava.util.Map;importorg…

    2022年6月5日
    33
  • JMM概述_jmi名词解释

    JMM概述_jmi名词解释简介什么是JMM内存模型可以理解为在特定的操作协议下,对特定的内存或者高速缓存进行读写访问的过程抽象描述,不同架构下的物理机拥有不一样的内存模型,Java虚拟机是一个实现了跨平台的虚拟系统,因此它也有自己的内存模型,即Java内存模型(JavaMemoryModel,JMM)。因此它不是对物理内存的规范,而是在虚拟机基础上进行的规范从而实现平台一致性,以达到Java程序能够“一次编写,到处运行

    2025年9月15日
    6
  • 【程序人生】有个程序员男朋友是什么体验?被公开吐槽

    【程序人生】有个程序员男朋友是什么体验?被公开吐槽我正在参与CSDN《新程序员》有奖征文

    2022年5月1日
    46
  • 【kali】kali设置burpsuite抓包dvwa

    【kali】kali设置burpsuite抓包dvwakali自带burpsuite配置代理burpsuite是通过代理来抓包dvwa的burpsuite:proxy—>options里边监听的应该是127.0.0.1:8080(端口ip如果撞车了都可以自己改)火狐:preferences–>最下边的networksettings点击settings—>从usesysyemproxy改成manualproxyhttp:127.0.0.1port:8080(和burpsuite设置的一样就ok),勾选上u

    2022年6月4日
    85

发表回复

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

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