OTSU算法学习 OTSU公式证明
OTSU算法学习 OTSU公式证明
1 otsu的公式如下,如果当前阈值为t,
w0 前景点所占比例
w1 = 1- w0 背景点所占比例
u0 = 前景灰度均值
u1 = 背景灰度均值
u = w0*u0 + w1*u1 全局灰度均值
g = w0(u0-u)*(u0-u) + w1(u1-u)*(u1-u) = w0*(1 – w0)*(u0 - u1)* (u0 - u1)
目标函数为g, g越大,t就是越好的阈值.为什么采用这个函数作为判别依据,直观是这个函数反映了前景和背景的差值.
差值越大,阈值越好.
下面是一段证明g的推导的matlab代码
|
syms w0 u0 u1 %w0 前景均值 u0 前景灰度均值 u1 背景灰度均值 %背景均值 w1 - w0; %全局灰度均值 u=w0*u0+w1*u1; %目标函数 g=w0*(u0-u)*(u0-u)+w1*(u1-u)*(u1-u); %化简的形式 g1 =w0*w1*(u0-u1)*(u0-u1); %因式展开 a1 = expand(g)%结果是 - u0^2*w0^2 + u0^2*w0 + 2*u0*u1*w0^2 - 2*u0*u1*w0 - u1^2*w0^2 + u1^2*w0 a2 = expand(g)%结果是 - u0^2*w0^2 + u0^2*w0 + 2*u0*u1*w0^2 - 2*u0*u1*w0 - u1^2*w0^2 + u1^2*w0 %对g进行因式分解 a2 = factor(g)%结果 -w0*(u0 - u1)^2*(w0 - 1) |
这里是matlab初等代数运算的讲解 http://wenku.baidu.com/link?url=SODqdtPjbNLhKPEvCjsHkOhMi9LMb34qIrnp9_QRBKUNqPLGLxRCuLJgL2sp1vhLk55b6hpp242-RTCVp6ma_7a7-0imT3WVyBcsTmQ-5HS
2 关于最大类间方差法(otsu)的性能:
类间方差法对噪音和目标大小十分敏感,它仅对类间方差为单峰的图像产生较好的分割效果。
当目标与背景的大小比例悬殊时,类间方差准则函数可能呈现双峰或多峰,此时效果不好,但是类间方差法是用时最少的。
3 代码实现
|
public int GetThreshValue(Bitmap image) { BitmapData bd , image.Width, image.Height), ImageLockMode.WriteOnly, image.PixelFormat); byte* pt =(byte*)bd.Scan0; 个点 byte color; byte* pline; int n, n1, n2; int total;//total为总和,累计值 double m1, m2, sum, csum, fmax, sb;//sb为类间方差,fmax存储最大方差值 int k, t, q; ;// 阈值 ; switch(image.PixelFormat) { case PixelFormat.Format24bppRgb: step ; break; case PixelFormat.Format32bppArgb: step ; break; case PixelFormat.Format8bppIndexed: step ; break; } //生成直方图 ; i < image.Height; i++) { pline = pt + i * bd.Stride; ; j < image.Width; j++) { color =*(pline + j * step);//返回各个点的颜色,以RGB表示 pixelNum } } //直方图平滑化 ; k++) { total ; 个灰度做平滑化,t值应取较小的值 { q = k + t; )//越界处理 q ; ) q ; total = total + pixelNum[q];//total为总和,累计值 } //个+中间1个+右边2个灰度,共5个,所以总和除以5,后面加0.5是用修正值 pixelNum[k]=(int)((float)total /5.0+0.5); } //求阈值 sum = csum =0.0; n ; //计算总的图象的点数和质量矩,为后面的计算做准备 ; k++) { //x*f(x)质量矩,也就是每个灰度的值乘以其点数(归一化后为概率),sum为其总和 sum +=(double)k *(double)pixelNum[k]; n += pixelNum[k];//n为图象总的点数,归一化后就是累积概率 } fmax =-1.0;//类间方差sb不可能为负,所以fmax初始值为-1不影响计算的进行 n1 ; 到255)计算一次分割后的类间方差sb { n1 += pixelNum[k];//n1为在当前阈值遍前景图象的点数 ){continue;}//没有分出前景后景 n2 = n - n1;//n2为背景图象的点数 //n2表示全部都是后景图象,与n1=0情况类似,之后的遍历不可能使前景点数增加,所以此时可以退出循环 ){break;} csum +=(double)k * pixelNum[k];//前景的“灰度的值*其点数”的总和 m1 = csum / n1;//m1为前景的平均灰度 m2 =(sum - csum)/ n2;//m2为背景的平均灰度 sb =(double)n1 *(double)n2 *(m1 - m2)*(m1 - m2);//sb为类间方差 if(sb > fmax)//如果算出的类间方差大于前一次算出的类间方差 { fmax = sb;//fmax始终为最大类间方差(otsu) threshValue = k;//取最大类间方差时对应的灰度的k就是最佳阈值 } } image.UnlockBits(bd); image.Dispose(); return threshValue; } |
4 二维otsu算法
下图是二维otsu的立体图,是对右边的A进行二维直方图统计得到的图像, 遍历区域为5*5.


这是对应的matlab代码
|
%统计二维直方图 i 当前点的亮度 j n*n邻域均值亮度 function hist2 = hist2Function(image, n) %初始化255*2565矩阵 hist2 ); [height, width]= size(image); :height :width data = image(i,j); tempSum =0.0; :n :n x = i + l; y = j+m;
x ; elseif x > width x = width; end
y ; elseif y > height y = height; end tempSum = tempSum + double(image(y,x)); end end tempSum )); hist2; end end %加载图像 imagea = imread('a.bmp'); %显示图像 %imshow(imagea); %显示直方图 %figure;imhist(imagea); %计算二维直方图 hist2 ); %显示二维直方图 ); mesh(x,y,hist2) |
<灰度图象的二维Otsu自动阈值分割法.pdf> 这篇文章讲解的不错.文章这里有下载http://download.csdn.net/detail/wisdomfriend/9046341
下面用数学语言表达一下
i :表示亮度的维度
j : 表示点区域均值的维度
w0: 表示在阈值(s,t)时 所占的比例
w1: 表示在阈值(s,t)时, 所占的比例
u0(u0i, u0j): 表示在阈值(s,t)时时 的均值.u0时2维的
u1(u1i, u1j): 表示在阈值(s,t)时的均值.u1时2维的
uT: 全局均值
和一维otsut函数类似的目标函数
sb = w0(u0-uT)*(u0-uT)’ + w1(u1-uT)*(u1-uT)’
= w0[(u0i-uTi)* (u0i-uTi) + (u0j-uTj)* (u0j-uTj)] + w1[(u1i-uTi)* (u1i-uTi) + (u1j-uTj)* (u1j-uTj)]
这里是代码实现.出自这篇文章:http://blog.csdn.net/yao_wust/article/details/23531031
|
]; ]; ];//Pst_0用来存储概率分布情况 ];//存储x方向上的均值矢量 int OTSU2d(IplImage * src) { int height = src->height; int width = src->width; long pixel = height * width; int i,j; ;i++)//初始化直方图 { ;j++) histogram; } IplImage ); cvSmooth); ;i < height;i++)//计算直方图 { ; j < width;j++) { int data1 = cvGetReal2D(src,i,j); int data2 = cvGetReal2D(temp,i,j); histogram[data1][data2]++; } } ;i++)//直方图归一化 ;j++) p_histogram[i][j]=(histogram[i][j]*1.0)/(pixel*1.0); Pst_0]; ;i++)//计算概率分布情况 ;j++) { double temp =0.0; ) temp ][j]; ) temp ]; ) temp ]; temp = temp + p_histogram[i][j]; Pst_0[i][j]= temp; } Xst_0]; ;i++)//计算x方向上的均值矢量 ;j++) { double temp =0.0; ) temp ][j]; ) temp ]; ) temp ]; temp = temp + i * p_histogram[i][j]; Xst_0[i][j]= temp; } ];//存储y方向上的均值矢量 Yst_0]; ;i++)//计算y方向上的均值矢量 ;j++) { double temp =0.0; ) temp ][j]; ) temp ]; ) temp ]; temp = temp + j * p_histogram[i][j]; Yst_0[i][j]= temp; } int threshold1; int threshold2; double variance =0.0; double maxvariance =0.0; ;i++)//计算类间离散测度 ;j++) { longdouble p0 = Pst_0[i][j]; ); ]+Pst_0[i][j]; ]+Xst_0[i][j]; ]+Yst_0[i][j]; ); variance = p0*v0+p1*v1; if(variance > maxvariance) { maxvariance = variance; threshold1 = i; threshold2 = j; } } //printf("%d %d",threshold1,threshold2); ; } |
总结: 二维otsu算法得到一个阈值,然后对图像做二值化.仍然不能解决光照不均匀二值化的问题.比一维otsu效果好一些,但不是很明显.这个算法的亮点在于考虑的点的附近区域的均值.
OTSU算法学习 OTSU公式证明的更多相关文章
- 实现 RSA 算法之基础公式证明(第一章)(老物)
写这篇日志是拖了很久的事情,以前说要写些算法相关的文章给想学信息安全学(简称信安),密码学的同学提供些入门资料,毕竟这种知识教师上课也不会细讲太多(纯理论偏重),更不用说理解和应用了,说到RSA公钥( ...
- 《opencv学习》 之 OTSU算法实现二值化
主要讲解OTSU算法实现图像二值化: 1.统计灰度级图像中每个像素值的个数. 2.计算第一步个数占整个图像的比例. 3.计算每个阈值[0-255]条件下,背景和前景所包含像素值总个数和总概率(就 ...
- 基于Otsu算法的图像自适应阈值切割
在图像处理实践中,将灰度图转化为二值图是非经常见的一种预处理手段. 在Matlab中,能够使用函数BW = im2bw(I, level)来将一幅灰度图 I.转化为二值图. 当中.參数level是一个 ...
- 大津法---OTSU算法
简介: 大津法(OTSU)是一种确定图像二值化分割阈值的算法,由日本学者大津于1979年提出.从大津法的原理上来讲,该方法又称作最大类间方差法,因为按照大津法求得的阈值进行图像二值化分割后,前景与背景 ...
- 自适应阈值分割—大津法(OTSU算法)C++实现
大津法是一种图像灰度自适应的阈值分割算法,是1979年由日本学者大津提出,并由他的名字命名的.大津法按照图像上灰度值的分布,将图像分成背景和前景两部分看待,前景就是我们要按照阈值分割出来的部分.背景和 ...
- 用OpenCV实现Otsu算法
算法的介绍 otsu法(最大类间方差法,有时也称之为大津算法)使用的是聚类的思想,把图像的灰度数按灰度级分成2个部分,使得两个部分之间的灰度值差异最大,每个部分之间的灰度差异最小,通过方差的计算来寻找 ...
- 二次剩余Cipolla算法学习笔记
对于同余式 \[x^2 \equiv n \pmod p\] 若对于给定的\(n, P\),存在\(x\)满足上面的式子,则乘\(n\)在模\(p\)意义下是二次剩余,否则为非二次剩余 我们需要计算的 ...
- 算法学习之C语言基础
算法学习,先熟悉一下C语言哈!!! #include <conio.h> #include<stdio.h> int main(){ printf(+); getch(); ; ...
- PCA算法学习(Matlab实现)
PCA(主成分分析)算法,主要用于数据降维,保留了数据集中对方差贡献最大的若干个特征来达到简化数据集的目的. 实现数据降维的步骤: 1.将原始数据中的每一个样本用向量表示,把所有样本组合起来构成一个矩 ...
随机推荐
- Python小白学习之路(四)——第一次练习题
写在前面: 今天下雪了呢!连着两天都没有更新学习记录. 我没有偷懒呢.做了一天的练习题,昨天学的内容还没总结完,太累了就回去睡觉了 连续一周早起,强大的内心也无法支撑我疲惫的身体 今天早起做了整理.加 ...
- Java虚拟机的内存组成
查了诸多的地方看到的都是这样一句话,我也Copy过来. 按照官方的说法:"Java 虚拟机具有一个堆,堆是运行时数据区域,所有类实例和数组的内存均从此处分配.堆是在 Java 虚拟机启动时创 ...
- L09-Linux系统修改网卡名称(eth1修改为eth0)
一.环境 VirtualBox + CentOS6.5 二.问题 有时候在克隆服务器之后配置网络时,或者在维护别人建好的服务器时,会遇到这样一种情况.如下图所示: 即:在接口配置文件ifcfg-e ...
- (转)Oracle 12c Windows安装、介绍及简单使用(图文)
版权声明:http://blog.csdn.net/anxpp https://blog.csdn.net/anxpp/article/details/51345074 转载请注明出处:http:// ...
- CAJ Viewer安装流程以及CAJ或Pdf转换为Word格式
不多说,直接上干货! pdf转word格式,最简单的就是,实用工具 Adobe Acrobat DC 首先声明的是,将CAJ或者Pdf转换成Word文档,包括里面的文字.图片以及格式,根本不需 ...
- 【转】Hadoop vs Spark性能对比
原文地址:http://www.cnblogs.com/jerrylead/archive/2012/08/13/2636149.html 基于Spark-0.4和Hadoop-0.20.2 1. K ...
- C/C++ -- Gui编程 -- Qt库的使用 -- HelloWorld
1.纯代码写对话框HelloWorld 创建空Qt工程,添加C++源文件main.cpp 需要设置编码以支持中文 -----源代码main.cpp----- #include <QApplica ...
- Etcd安全配置之Basic Auth认证
<中小团队落地配置中心详解>文章中我们介绍了如何基于Etcd+Confd构建配置中心,最后提到Etcd的安全问题时说了可以使用账号密码认证以达到安全访问的目的,究竟该如何开启认证以及怎么设 ...
- 深度学习--RNN,LSTM
一.RNN 1.定义 递归神经网络(RNN)是两种人工神经网络的总称.一种是时间递归神经网络(recurrent neural network),另一种是结构递归神经网络(recursive neur ...
- CentOS6.5安装php7+nginx+mysql实现安装WordPress
安装php7+nginx参考该博客http://blog.csdn.net/whatday/article/details/50645117 安装php7参考http://blog.csdn.net/ ...