介绍

Ostu方法又名最大类间差方法,通过统计整个图像的直方图特性来实现全局阈值T的自动选取,其算法步骤为:

  1. 先计算图像的直方图,即将图像所有的像素点按照0~255共256个bin,统计落在每个bin的像素点数量

  2. 归一化直方图,也即将每个bin中像素点数量除以总的像素点

  3. i表示分类的阈值,也即一个灰度级,从0开始迭代

  4. 通过归一化的直方图,统计0~i 灰度级的像素(假设像素值在此范围的像素叫做前景像素) 所占整幅图像的比例w0,并统计前景像素的平均灰度u0;统计i~255灰度级的像素(假设像素值在此范围的像素叫做背景像素) 所占整幅图像的比例w1,并统计背景像素的平均灰度u1;

  5. 计算前景像素和背景像素的方差 g = w0*w1*(u0-u1) (u0-u1)

  6. i++;转到4),直到i为256时结束迭代

7)将最大g相应的i值作为图像的全局阈值

#include "opencv2/core/core.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp" using namespace cv; #include <iostream> int getOstu(const Mat & in); int main()
{
Mat img = imread("mobile2.jpeg" ,0);
Mat img_high_Light = imread("mobile3.jpeg" ,0);
Mat dst , dst_HL; if(img.empty() | img_high_Light.empty())
{
std::cout<<"Error!!";
return -1;
} std::cout<<"The return value of getOstu is: "<<getOstu(img);
std::cout<<"\n"<<"The return value of opencv threshold is: "<<threshold(img , dst ,0,255,CV_THRESH_OTSU);//opencv已实现的大津法 imshow("origin" ,img);
imshow("new" , dst); waitKey(0); threshold(img_high_Light , dst_HL ,0,255,CV_THRESH_OTSU);
imshow("origin" ,img_high_Light );
imshow("new", dst_HL); waitKey(0); return 0;
} int getOstu(const Mat & in)
{
int rows = in.rows;
int cols = in.cols;
long size = rows * cols; float histogram[256] = {0};
for( int i = 0; i < rows; ++i)
{
//获取第 i行首像素指针
const uchar * p = in.ptr<uchar>(i);
//对第i 行的每个像素(byte)操作
for( int j = 0; j < cols; ++j )
{
histogram[int(*p++)]++;
}
}
int threshold;
long sum0 = 0, sum1 = 0; //存储前景的灰度总和及背景灰度总和
long cnt0 = 0, cnt1 = 0; //前景的总个数及背景的总个数
double w0 = 0, w1 = 0; //前景及背景所占整幅图像的比例
double u0 = 0, u1 = 0; //前景及背景的平均灰度
double variance = 0; //最大类间方差 double maxVariance = 0;
for(int i = 1; i < 256; i++) //一次遍历每个像素
{
sum0 = 0;
sum1 = 0;
cnt0 = 0;
cnt1 = 0;
w0 = 0;
w1 = 0;
for(int j = 0; j < i; j++)
{
cnt0 += histogram[j];
sum0 += j * histogram[j];
} u0 = (double)sum0 / cnt0;
w0 = (double)cnt0 / size; for(int j = i ; j <= 255; j++)
{
cnt1 += histogram[j];
sum1 += j * histogram[j];
} u1 = (double)sum1 / cnt1;
w1 = 1 - w0; // (double)cnt1 / size; variance = w0 * w1 * (u0 - u1) * (u0 - u1);
if(variance > maxVariance)
{
maxVariance = variance;
threshold = i;
}
} return threshold;
}

缺陷

OSTU算法在处理光照不均匀的图像的时候,效果会明显不好,因为利用的是全局像素信息。

OSTU二值化算法的更多相关文章

  1. Wellner 自适应阈值二值化算法

    参考文档: Adaptive Thresholding for the DigitalDesk.pdf       Adaptive Thresholding Using the Integral I ...

  2. sauvola二值化算法研究

    sauvola二值化算法研究   sauvola是一种考虑局部均值亮度的图像二值化方法, 以局部均值为基准在根据标准差做些微调.算法实现上一般用积分图方法 来实现.这个方法能很好的解决全局阈值方法的短 ...

  3. 一种局部二值化算法:Sauvola算法

    之前接触过全局二值化(OTSU算法),还有OPENCV提供的自适应二值化,最近又了解到一种新的局部二值化算法,Sauvola算法. 转载自:http://www.dididongdong.com/ar ...

  4. 基于Simple Image Statistics(简单图像统计,SIS)的图像二值化算法。

    这是个简单的算法,是全局二值算法的一种,算法执行速度快. 算法过程简单描述如下: 对于每一个像素,做如下处理 1.计算当前像素水平和垂直方向的梯度. (two gradients are calcul ...

  5. [转载+原创]Emgu CV on C# (四) —— Emgu CV on 全局固定阈值二值化

    重点介绍了全局二值化原理及数学实现,并利用emgucv方法编程实现. 一.理论概述(转载,如果懂图像处理,可以略过,仅用作科普,或者写文章凑字数)  1.概述 图像二值化是图像处理中的一项基本技术,也 ...

  6. 【转】Emgu CV on C# (五) —— Emgu CV on 局部自适应阈值二值化

    局部自适应阈值二值化 相对全局阈值二值化,自然就有局部自适应阈值二值化,本文利用Emgu CV实现局部自适应阈值二值化算法,并通过调节block大小,实现图像的边缘检测. 一.理论概述(转载自< ...

  7. [转载+原创]Emgu CV on C# (五) —— Emgu CV on 局部自适应阈值二值化

    局部自适应阈值二值化 相对全局阈值二值化,自然就有局部自适应阈值二值化,本文利用Emgu CV实现局部自适应阈值二值化算法,并通过调节block大小,实现图像的边缘检测. 一.理论概述(转载自< ...

  8. adaptiveThreshold自适应二值化源码分析

    自适应二值化介绍: 二值化算法是用输入像素的值I与一个值C来比较,根据比较结果确定输出值. 自适应二值化的每一个像素的比较值C都不同,比较值C由这个像素为中心的一个块范围计算在减去差值delta得到. ...

  9. Win8 Metro(C#)数字图像处理--2.59 P分位法图像二值化

    原文:Win8 Metro(C#)数字图像处理--2.59 P分位法图像二值化  [函数名称]   P分位法图像二值化 [算法说明]   所谓P分位法图像分割,就是在知道图像中目标所占的比率Rat ...

随机推荐

  1. python 之 多进程

    阅读目录 1. Process 2. Lock 3. Semaphore 4. Event 5. Queue 6. Pipe 7. Pool 序. multiprocessingpython中的多线程 ...

  2. src与href的异同

    相同点: 在跨域中,src,href,这些发送的请求都是get请求: 不同点: 1, 概念:href (Hypertext Reference)指定网络资源的位置: 理解:href 用作 " ...

  3. HDU 5894 hannnnah_j’s Biological Test

    题目链接:传送门 题目大意:有n张板凳围成一圈,有m个人,要让m个人都坐到凳子上且任意两人之间相隔>=k 个凳子,问有多少种方法%(1e9+7) 题目思路:组合数学 我们这样考虑,既然每个人相距 ...

  4. Java日志记录工具SLF4J介绍

    SLF4J是什么 SLF4J是一个包装类,典型的facade模式的工具,对用户呈现统一的操作方式,兼容各种主流的日志记录框架,典型的有log4j/jdk logging/nop/simple/jaka ...

  5. 巨蟒python全栈开发-第20天 核能来袭-约束 异常处理 MD5 日志处理

    一.今日主要内容 1.类的约束(对下面人的代码进行限制;项目经理的必备技能,要想走的长远) (1)写一个父类,父类中的某个方法要抛出一个异常 NotImplementedError(重点) (2)抽象 ...

  6. POJ 2253 Frogger【最短路变形——路径上最小的最大权】

    链接: http://poj.org/problem?id=2253 http://acm.hust.edu.cn/vjudge/contest/view.action?cid=22010#probl ...

  7. python装饰器的学习笔记

    此博文是我对装饰器的一些理解,如果有错误欢迎及时留言,我会第一时间向大家学习. 一.什么是装饰器 1.从字面意义来看: 是用来给函数装饰打扮的函数 2.理论上可以理解为: (1).不改变函数的运行方式 ...

  8. Python面向对象中的“私有化”

    Python面向对象中的“私有化” Python并不直接支持私有方式,而要靠程序员自己把握在外部进行特性修改的时机. 为了让方法或者特性变为私有(从外部无法访问),只要在它的名字前面加上双下划线即可. ...

  9. MySQL数据库(3)- 完整性约束、外键的变种、单表查询

    一.完整性约束 在创建表时候,约束条件和数据类型的宽度都是可选参数. 作用:用于保证数据的完整性和一致性. 1.not null(不可空)与default 示例一:插入一个空值,如下: mysql&g ...

  10. 在python中如何使用多进制数字

    我们在python中,除十进制外还可以使用二进制.八进制和十六进制 1.二进制数字由0和1组成,我们使用0b或0B前缀表示二进制数 2.使用bin()函数将一个数字转换为它的二进制形式 print(b ...