详细及易读懂的 大津法(OTSU)原理 和 比opencv自带更快的算法实现

2023-11-11

OTSU算法原理简述:

最大类间方差是由日本学者大津(Nobuyuki Otsu)于1979年提出,是一种自适应的阈值确定方法。算法假设图像像素能够根据阈值,被分成背景[background]和目标[objects]两部分。然后,计算该最佳阈值来区分这两类像素,使得两类像素区分度最大。

公式:  记 M = 256 单通道灰度分级 Sum = 像素总数

  1. 背景像素占比 \omega1 = \frac{N1}{Sum}  
  2. 前景像素占比\omega2 = 1- \omega1 = \frac{N2}{Sum} =1- \frac{N1}{Sum}
  3. 背景的平均灰度值\mu 1 = \sum_{i = 0}^{t} i *Pr(i | C_{0}) = \sum_{i = 0}^{t} i *Pi / \sum_{i = 0}^{t} Pi = \frac{\mu(t))}{\omega_{1}}
  4. 前景的平均灰度值\mu 2 = \sum_{i = t+1}^{M - 1} i *Pr(i | C_{1}) = \sum_{i = t+1}^{M - 1} i *Pi / \sum_{i = t+1}^{M - 1} Pi = \frac{\mu - \mu(t))}{\omega _{2}}
  5. 0~M灰度区间的灰度累计值\mu = \mu1*\omega 1 + \mu2*\omega 2
  6. 类间方差:g = \omega 1 * (\mu - \mu1)^{2} + \omega 2 * (\mu - \mu2)^{2}
  7. 将公式3.4.5带入公式6 可得最终简化公式: g = \omega 1 * \omega2 * (\mu1 - \mu2)^{2}

 3、4的意思:每个灰度(0~255)比例 * 当前灰度的和。

代码:

#include <opencv2\opencv.hpp>
#include <iostream>
#include <time.h>
using namespace std;
using namespace cv;

int myOtsu(Mat & src, Mat &dst)
{
	
	int th = 0;
	const int GrayScale = 256;	//单通道图像总灰度256级
	int pixCount[GrayScale] = { 0 };//每个灰度值所占像素个数
	int pixSum = src.cols * src.rows;//图像总像素点
	float pixPro[GrayScale] = { 0 };//每个灰度值所占总像素比例
	float SumpixPro[GrayScale] = { 0 }; // 比例的和
	float WpixPro[GrayScale] = { 0 }; //比例 * 权重
	float SumWpixPro[GrayScale] = { 0 };//比例 * 权重 的 和
	float w0, w1, u0tmp, u1tmp, u0, u1, deltaTmp, deltaMax = 0;
	double start = getTickCount(); //开始时间
	for (int i = 0; i < src.rows; i++)
	{
		for (int j = 0; j < src.cols; j++)
		{
			int index = i * src.cols + j;
			pixCount[src.data[index]]++;//统计每个灰度级中像素的个数  
		}
	}
	double c1 = getTickCount(); 
	//cout << "c1 >> " << (c1 - start) / getTickFrequency() << endl;//输出时间
	for (int i = 0; i < GrayScale; i++)
	{
		pixPro[i] = pixCount[i] * 1.0 / pixSum;//计算每个灰度级的像素数目占整幅图像的比例  
		WpixPro[i] = i * pixPro[i];
		if (i == 0)
		{
			SumWpixPro[i] += WpixPro[i];
			SumpixPro[i] += pixPro[i];
		}
		else
		{
			SumWpixPro[i] = WpixPro[i] + SumWpixPro[i - 1];
			SumpixPro[i] = pixPro[i] + SumpixPro[i - 1];
		}
	}

	for (int i = 0; i < GrayScale; i++)//遍历所有从0到255灰度级的阈值分割条件,测试哪一个的类间方差最大
	{
		w0 = w1 = u0tmp = u1tmp = u0 = u1 = deltaTmp = 0;
		/*for (int j = 0; j < GrayScale; j++)
		{
			if (j <= i)//背景
			{
				w0 += pixPro[j];
				u0tmp += WpixPro[j];
			}
			else//前景
			{
				w1 += pixPro[j];
				u1tmp += WpixPro[j];
			}
		}*/
		w0 = SumpixPro[i];
		w1 = 1 - w0;
		
		if (w0 == 0 || w1 == 0)
			continue;
		u0tmp = SumWpixPro[i];
		u1tmp = SumWpixPro[255] - SumWpixPro[i];
		
		u0 = u0tmp / w0;
		u1 = u1tmp / w1;
		deltaTmp = (float)(w0 *w1* pow((u0 - u1), 2)); //类间方差公式 g = w1 * w2 * (u1 - u2) ^ 2
		if (deltaTmp > deltaMax)
		{
			deltaMax = deltaTmp;
			th = i;
		}
	}
	double c2 = getTickCount();
	//cout << "c2 >> " << (c2 - c1) / getTickFrequency() << endl;//输出时间
	for (int i = 0; i < src.rows; i++)
	{
		for (int j = 0; j < src.cols; j++)
		{
			int index = i * src.cols + j;
			if (src.data[index] > th)
				dst.data[index] = 255;
			else
				dst.data[index] = 0;
		}
	}
	double c3 = getTickCount();
	//cout << "c3 >> " << (c3 - c2) / getTickFrequency() << endl;//输出时间
	return th;
}

int main()
{
	Mat src = imread("scene.jpg", IMREAD_GRAYSCALE);//单通道读取图像
												   /*my_dst: 自己实现的大津法 得到的处理图像
												   otsu_dst:opencv自带的大津法 得到的处理图像
												   sub:两个处理图像相差图
												   */
	Mat my_dst, otsu_dst, sub;
	/*my_th: 自己实现的大津法 得到的最大类件方差 即阈值
	th:opencv自带的大津法 得到的最大类件方差 即阈值
	*/
	int my_th, th;

	/*计算开销时间,对比两个算法效率*/
	int times = 100;
	
	double start = getTickCount(); //开始时间
	my_dst = Mat::zeros(src.size(), CV_8UC1);
	while(times--)
	{
		
		my_th = myOtsu(src, my_dst);
	}
	double end = getTickCount();   //结束时间
	cout << "myOtsu end algorithm >> " << (end - start) / getTickFrequency() << endl; //输出时间
	cout << "myOtsu threshold >> " << my_th << endl;

	start = getTickCount(); //开始时间
	times = 100;
	while(times--)
	{
		th = threshold(src, otsu_dst, 0, 255, THRESH_OTSU);
	}
	end = getTickCount();   //结束时间
	cout << "Otsu end algorithm >> " << (end - start) / getTickFrequency() << endl;//输出时间
	cout << "Otsu threshold >> " << th << endl;


	waitKey();
	system("pause");
	return 0;
}

原图:用的是1920*1080的图像,循环100次得到测试结果和图像。

结论:可以看到自己实现的otsu和opencv自带的自适应阈值算法效率上相差大约3倍左右。

分析:遍历图片没有加速,opencv内部有加速。

分析时间慢的原因:第一次遍历整张图片,统计每个灰度级像素个数,第二次遍历整张图片进行阈值操作。

似曾相识第一次遍历不就是灰度直方图吗,然后第二次遍历不就是LUT图像压缩。

改进后源码:

#if 1
#include <opencv2\opencv.hpp>
#include <iostream>
#include <time.h>
using namespace std;
using namespace cv;

void getHistogram(Mat &src, int *dst)
{
	Mat hist;
	int channels[1] = { 0 };
	int histSize[1] = { 256 };
	float hranges[2] = { 0, 256.0 };
	const float *ranges[1] = { hranges };
	calcHist(&src, 1, channels, Mat(), hist, 1, histSize, ranges);
	//cout << hist ;
	for (int i = 0; i < 256; i++)
	{ 
		float binVal = hist.at<float>(i);
		dst[i] = int(binVal);
	}
}


int myOtsu(Mat & src, Mat &dst)
{
	
	int th = 0;
	const int GrayScale = 256;	//单通道图像总灰度256级
	int pixCount[GrayScale] = { 0 };//每个灰度值所占像素个数
	int pixSum = src.cols * src.rows;//图像总像素点
	float pixPro[GrayScale] = { 0 };//每个灰度值所占总像素比例
	float SumpixPro[GrayScale] = { 0 }; // 比例的和
	float WpixPro[GrayScale] = { 0 }; //比例 * 权重
	float SumWpixPro[GrayScale] = { 0 };//比例 * 权重 的 和
	float w0, w1, u0tmp, u1tmp, u0, u1, deltaTmp, deltaMax = 0;
	double start = getTickCount(); //开始时间
	
	/*for (int i = 0; i < src.rows; i++)
	{
		for (int j = 0; j < src.cols; j++)
		{
			int index = i * src.cols + j;
			pixCount[src.data[index]]++;//统计每个灰度级中像素的个数  
		}
	}*/
	getHistogram(src, pixCount);

	double c1 = getTickCount(); 
	//cout << "c1 >> " << (c1 - start) / getTickFrequency() << endl;//输出时间
	for (int i = 0; i < GrayScale; i++)
	{
		pixPro[i] = pixCount[i] * 1.0 / pixSum;//计算每个灰度级的像素数目占整幅图像的比例  
		WpixPro[i] = i * pixPro[i];
		if (i == 0)
		{
			SumWpixPro[i] += WpixPro[i];
			SumpixPro[i] += pixPro[i];
		}
		else
		{
			SumWpixPro[i] = WpixPro[i] + SumWpixPro[i - 1];
			SumpixPro[i] = pixPro[i] + SumpixPro[i - 1];
		}
	}

	for (int i = 0; i < GrayScale; i++)//遍历所有从0到255灰度级的阈值分割条件,测试哪一个的类间方差最大
	{
		w0 = w1 = u0tmp = u1tmp = u0 = u1 = deltaTmp = 0;
		/*for (int j = 0; j < GrayScale; j++)
		{
			if (j <= i)//背景
			{
				w0 += pixPro[j];
				u0tmp += WpixPro[j];
			}
			else//前景
			{
				w1 += pixPro[j];
				u1tmp += WpixPro[j];
			}
		}*/
		w0 = SumpixPro[i];
		w1 = 1 - w0;
		
		if (w0 == 0 || w1 == 0)
			continue;
		u0tmp = SumWpixPro[i];
		u1tmp = SumWpixPro[255] - SumWpixPro[i];
		
		u0 = u0tmp / w0;
		u1 = u1tmp / w1;
		deltaTmp = (float)(w0 *w1* pow((u0 - u1), 2)); //类间方差公式 g = w1 * w2 * (u1 - u2) ^ 2
		if (deltaTmp > deltaMax)
		{
			deltaMax = deltaTmp;
			th = i;
		}
	}
	double c2 = getTickCount();
	//cout << "c2 >> " << (c2 - c1) / getTickFrequency() << endl;//输出时间
	uchar lutData[256];
	for (int i = 0; i < 256; i++)
	{ 
		if (i > th)
			lutData[i] = 255;
		else
			lutData[i] = 0;
	}
	Mat lut(1, 256, CV_8UC1, lutData);
	LUT(src, lut, dst);
	/*for (int i = 0; i < src.rows; i++)
	{
		for (int j = 0; j < src.cols; j++)
		{
			int index = i * src.cols + j;
			if (src.data[index] > th)
				dst.data[index] = 255;
			else
				dst.data[index] = 0;
		}
	}*/
	double c3 = getTickCount();
	//cout << "c3 >> " << (c3 - c2) / getTickFrequency() << endl;//输出时间
	return th;
}

int main()
{
	Mat src = imread("scene.jpg", IMREAD_GRAYSCALE);//单通道读取图像
												   /*my_dst: 自己实现的大津法 得到的处理图像
												   otsu_dst:opencv自带的大津法 得到的处理图像
												   sub:两个处理图像相差图
												   */
	//Mat src = Mat(Size(3000, 3000), CV_8UC1, Scalar(127));
	Mat my_dst, otsu_dst, sub;
	/*my_th: 自己实现的大津法 得到的最大类件方差 即阈值
	th:opencv自带的大津法 得到的最大类件方差 即阈值
	*/
	int my_th, th;

	/*计算开销时间,对比两个算法效率*/
	int times = 100;
	
	double start = getTickCount(); //开始时间
	my_dst = Mat::zeros(src.size(), CV_8UC1);
	while(times--)
	{
		
		my_th = myOtsu(src, my_dst);
	}
	double end = getTickCount();   //结束时间
	cout << "myOtsu end algorithm >> " << (end - start) / getTickFrequency() << endl; //输出时间
	cout << "myOtsu threshold >> " << my_th << endl;

	start = getTickCount(); //开始时间
	times = 100;
	while(times--)
	{
		th = threshold(src, otsu_dst, 0, 255, THRESH_OTSU);
	}
	end = getTickCount();   //结束时间
	cout << "Otsu end algorithm >> " << (end - start) / getTickFrequency() << endl;//输出时间
	cout << "Otsu threshold >> " << th << endl;


	waitKey();
	system("pause");
	return 0;
}
#endif

发现优化后的效率比opencv自带的还快。

最后:欢迎大家的批评,很高心与大家分享,谢谢大家。

 

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

详细及易读懂的 大津法(OTSU)原理 和 比opencv自带更快的算法实现 的相关文章

  • Python中的类——完美描述现实世界的事物

    Python学习 类 目录 Python学习 类 前言 类的基础语法 定义 构造方法 继承 掠夺 前言 众所周知 现实世界的事物由两部分组成 即属性和行为 类也可以包含属性和行为 所以描述现实世界事物是非常合适的 例如 属性 灰发中分背带裤
  • java之Excel处理工具类

    package com hxy thesis common utils import com hxy thesis ht domain import com hxy thesis xp domain XpUserDO import org
  • 求数组中连续n个元素使其和最大

    给定一个数组 求出数组中连续的一些元素使其和的值最大 如果所有元素都为正数 显然整个数组即为所求的 如果所有元素的值为负数 则所求的最大值为0 这是在编程珠玑上看到的 其时间复杂度由O n3 减为O n 了 public class Max
  • 大数据学习第2天----------------linux 安装mysql 出现安装依赖问题解决(centos7)

    问题 安装mysql过程中出现的依赖 root hadoop mysql 5 7 16 rpm ivh mysql community devel 5 7 16 1 el7 x86 64 rpm warning mysql communit
  • 实录:SUSE服务器下的LVM配置

    SUSE Linux 存储阵列目前是主流应用 根据自己的工程经验 以下总结下suse 服务器下如何使用LVM管理软件进行阵列配置 在SUSE服务器对阵列进行配置一般有两种模式 1 直接使用fdisk 外挂存储设备名 对其进行分区划分 使用f
  • 【Linux】浅谈网络协议栈-网桥br0

    目录 1 什么是桥接 2 linux的桥接实现 3 网桥的功能 4 网桥的配置 1 什么是桥接 简单来说 桥接就是把一台机器上的若干个网络接口 连接 起来 其结果是 其中一个网口收到的报文会被复制给其他网口并发送出去 以使得网口之间的报文能
  • 计算机软件研究方法与技术路线,研究方法与技术路线

    研究方法与技术路线 由会员分享 可在线阅读 更多相关 研究方法与技术路线 2页珍藏版 请在人人文库网上搜索 1 1 研究方法1 实地调查法 在凤阳县地区和安徽科技学院附近分别进行调查 实地了解凤阳县中小企业对财会人员的需求及招聘要求 2 问
  • 第38.2节 osg加载大tif-10.20活动直播资源&中秋活动参赛源码

    目录 本节内容 本节内容 根据2021 10 20直播活动的内容 使用VPB处理影像高程的示例 将资源进行打包 里面使用的是VS2019 若使用其它版本的VS 则需要对应的OSG编译包 则在此链接获取 osgChina权威发布 vs各版本第
  • Flutter 自定义单选按钮和自定义复选框

    Flutter 自定义单选按钮和自定义复选框 前言 一 自定义单选按钮 二 自定义复选框 总结 前言 在日常开发中 很多时候系统自带的单选按钮 复选框无法满足我们的需求 那么就需要自定义样式的按钮 本篇文章将记录如何自定义单选按钮 复选框
  • Vue实现Markdown

    前言 本文将介绍如何使用Vue和SpringBoot实现一个Markdown编辑器 其中Vue用于前端 SpringBoot用于后端 实现数据存储和接口调用 项目背景 Markdown是一种轻量级的标记语言 用于简化文本编辑 最初由John
  • 初等数学概论

    author hjjdebug date 2016年 01月 18日 星期一 21 36 50 CST article 初等数学概论 记得高中的哲学书上说的 真理是相对的 没有永恒 绝对的真理 而我们这里讨论的数学 却是永恒绝对的真理 放之
  • Unity中的Debug类调试使用

    UnityEngine Debug Class containing methods to ease debugging while developing a game 该类中包含了一些便于游戏开发时的调试方法 Class Variable
  • The content of element type “configuration“ must match “(properties?,settings?,typeAliases?,typeHand

    注意 每个标签必须按顺序写
  • 有源滤波器治理谐波好在哪

    减小谐波影响应对谐波源本身或在附近采取适当的措施 通常情况下 采用加装滤波器的方式治理谐波 滤波器一般分为无源滤波器和有源滤波器 下面领步 北京 根据多年的实践经验给出一个具体的解决方案 在有谐波问题是 什么样的选择才是最好的 谐波的危害
  • React---使用componentDidUpdate钩子函数判断路由地址是否发生变化

    在组件更新 例如组件的路由更新 后会执行componentDidUpdate钩子函数 componentDidUpdate方法会传入两个参数 prevProps prevState prevProps prevState可以拿到组件更新前的
  • Web3 入门手册:从认知到实践

    如果你也喜欢 Web3 希望在这做些有趣的 有意义的事情 那么我希望这篇文章可以帮助到你 送给想要进入 Web3 或者刚刚进入 Web3 的小伙伴 但是考虑到两点原因 我还是打算把这件事推迟一些时日 一是在各大媒体都鼓吹 All In We
  • 如何将pdf转换成txt?悄悄告诉你3个好用的转换方法

    pdf和txt文档都是我们经常会使用到的文档格式 这两种文档各有各的特点 pdf文档适合用于展示 而txt文档适合用于整理各种文字信息 在面对不同的情况时我们就要使用不同的文档 就比如将纯文字的资料进行搜集的时候 利用txt文档会更方便 而
  • 如何在vue中引入字体

    一 为什么要引入字体 在前端开发中 选用合适的字体往往会极大地提升网站的视觉体验 然而 网页中默认字体的种类和风格有限 且在不同的设备 浏览器上渲染效果不尽相同 因此 很多开发者会选择自定义字体来提升用户体验 二 如何引入字体 1 搜索下载
  • 2020华为杯数学建模总结

    2020研究生数学建模竞赛总结 题目 2020年中国研究生数学建模竞赛B题 降低汽油精制过程中的辛烷值损失模型 一 背景 汽油是小型车辆的主要燃料 汽油燃烧产生的尾气排放对大气环境有重要影响 为此 世界各国都制定了日益严格的汽油质量标准 见

随机推荐

  • linux 套接字文件类型,Linux下的文件类型

    Linux下的文件类型 1 开头 表示普通文件 2 d开头 表示目录文件 3 b开头 表示块设备 4 c开头 表示是字符设备 5 I开头 表示符号链接文件 6 p开头 表示管道文件pipe 7 s开头 表示套接字文件socket root
  • 浅谈BERT/Transformer模型的压缩与优化加速

    作者 姚益武 单位 阿里巴巴集团 研究方向 AI算法与工程架构 前言 BERT Transformer 结构及其变体 已成为自然语言处理 NLP 语音识别 ASR 等领域的主流序列建模结构 并且 相比于卷积操作的局部特征提取能力 以及平移不
  • 【Python】ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any

    一 问题描述 在使用Python的判断语句的时候 data2 data2 Month 11 and data2 Day 11 我的本意是想找出11月11日的数据 运用上面的代码 却得到了报错 报错信息 ValueError The trut
  • [QT编程系列-38]:数据存储 - SQLite数据库存储与操作

    目录 1 SQLite数据库概述 1 1 简介 1 2 SQLite不支持网络连接 1 3 SQLite不需要安装MySQL Server数据库 1 4 SQLite性能 1 5 SQLite支持的数据条目 2 SQLite操作示例 3 Q
  • 找不到插件 ‘org.springframework.boot:spring-boot-maven-plugin:‘问题

    出现pom文件找不到插件 org springframework boot spring boot maven plugin 问题 可能是因为版本没有绑定好 去一级父类依赖找对应的插件版本 在pom文件中加上 把父类的version加到po
  • 1小时学会CSS-下

    今天给大家分享的内容包含CSS 盒子模型 CSS 标准布局 CSS 浮动布局 并以案列进行详细说明 一 CSS 盒子模型 CSS 将所有元素都当成盒子 CSS布局其实就是如何堆放盒子 组成 content 内容 gt padding 内边距
  • 【c语言】小程序游戏——飞机游戏(二)

    在接下来 我们需要对飞机添加一些属性 1 利用键盘控制飞机的移动 2 按空格键可以发射激光 NO 1 利用键盘控制飞机的移动 首先我们需要了解的是 如果想要通过按键来控制飞机的移动 那么我们具体要怎么控制呢
  • Verilog(4)系统任务monitor,time,stop,random等,编译预处理语句

    调试用系统任务和常用编译预处理语句 用于调试和差错的系统任务 以及编写模块时的预处理语句 系统任务 monitor 提供了监控和输出参数列表中表达式或变量值的功能 参数列表中输出控制格式字符串和输出表列的规则和 d i s p l a
  • java基础之replace,replaceAll

    走在乡间的小路上 回首过往 以下代码结果都是显示在Console框中 所以 n会被解析成换行 n只显示 n 所以看到结果换行其实是输出了 n 看到输出 n 其实输出的是 n replace和replaceAll是编程中经常用到的替换函数 成
  • 求出1~N范围中所有的素数

    判断是否为素数 public static boolean isPrime int n int sqrt int Math sqrt n int i for i 2 i lt sqrt i if n i 0 break if i gt sq
  • 小程序瀑布流布局

    list wxml列表
  • Java的深浅拷贝机制

    Java的深浅拷贝机制 我们先理解一下深浅拷贝的概念 1 浅拷贝 Java在进行对象拷贝的过程中 对于他的成员变量进行拷贝 如果是基本数据类型 就会直接拷贝他的值 如果是引用类型 则会拷贝他的引用地址 而不会拷贝对象本身 2 深拷贝 Jav
  • Windows 10 和 Windows 11 有什么区别?

    Windows 10 和 Windows 11 有什么区别 Windows 11 具有 Windows 10 的全部功能和安全性 同时具有经重新设计而焕然一新的外观 它还自带一些新的工具 声音和应用 所有细节面面俱到 颜值 功能与安全性集于
  • Python字符串转为字典方法大全

    方法一 通过内置函数eval 1 2 3 4 5 6 7 8 9 10 11 12 13 str info name test age 18 dict info eval str info print string info type is
  • 【MYSQL】第一篇 Mysql如何处理百万级别的数据

    1 应尽量避免在 where子句中使用 或 lt gt 操作符 否则将引擎放弃使用索引而进行全表扫描 2 应尽量避免在 where子句中对字段进行 null值判断 否则将导致引擎放弃使用索引而进行全表扫描 3 尽量避免在 where子句中使
  • Jmeter性能测试 —— TPS拐点寻找

    寻找TPS性能拐点1 准备脚本 在本地电脑调试Jmeter压测脚本 上传到压测机Jmeter所在的服务器 2 执行压力测试 执行压测脚本 jmeter n t xianchengzuse jmx 记录业务压测数据 3 监控服务器性能指标 监
  • MySQL____高级查询、联合查询

    文章目录 一 聚合查询 1 count查询 总数统计 1 1count 用法1 1 2 count 用法2 1 3count 用法3 1 4 注意事项 2 SUM函数 总和统计 3 AVG函数 4 MAX函数 5 MIN函数 二 ifnul
  • 如何统计iOS产品不同渠道的下载量?

    一 前言 在开发过程中 Android可能会打出来很多的包 用于标识不同的商店下载量 原来觉得苹果只有一个商店 AppStore 如何做出不同来源的统计呢 本篇文章就是告诉大家如何做不同渠道来源统计 二 正文 先看一下苹果自家统计到的数据
  • unity局域网开关机步骤一-网络唤醒-设置电脑使允许局域网内其他电脑控制

    被控制端主机的设置 一 Bois界面网络唤醒的设置 外链图片转存失败 源站可能有防盗链机制 建议将图片保存下来直接上传 img TR2xwyAx 1593577482582 htts img blog csdnimg cn 20200701
  • 详细及易读懂的 大津法(OTSU)原理 和 比opencv自带更快的算法实现

    OTSU算法原理简述 最大类间方差是由日本学者大津 Nobuyuki Otsu 于1979年提出 是一种自适应的阈值确定方法 算法假设图像像素能够根据阈值 被分成背景 background 和目标 objects 两部分 然后 计算该最佳阈