Otsu算法(大律法或最大类间方差法)

合集下载

otsu算法——图像分割

otsu算法——图像分割
前景比例:
背景比例:
像素点总数:
前景和背景概率之和:
平均灰度值:
类间方差:
将公式(4)和(5)带入(6)可以得到等价公式:
核心代码:Histogram[data[i*srcimage.step + j]]++;//step指向每行的字节总量,date访问每个像素的值for (int i = 1; i < 255 ;i++)//从1开始遍历,寻找最合适的值{//每次遍历前需要初始化各变量w0 = 0; u0 = 0; w1 = 0; u1 = 0;for (int j = 0; j <= i; j++)//背景部分各值计算 { w0 += Histogram[j]; //背景部分像素点总数 u0 += j*Histogram[j]; //背景部分像素总灰度和 } u0 = u0 / w0; //背景像素平均灰度 w0 = w0 / number; //背景部分像素点所占比例}double varValueI = w1*w2*(u1 - u2)*(u1 - u2); //类间方差计算
算法过程:(1)设K(x,y)=f(x,y)/g(x,y)为像素点的 斜率,其中f(x,y)为点(x,y)的灰度值, g(x,y)为点(x,y)周围点的平均值。 (2)设阈值t1,t2将二维直方图分为A、B、 C三个区域。其中B区域代表前景和背 景像素点部分,而A、C代表边界点和 噪声点部分。
算法过程:(1)对于图像I(x,y),将前景与背景的分割阈值设为T。(2)将属于前景的像素点的个数占整个图像的比例设为w0,其平均灰度设为u0。(3)将属于背景的像素点的个数占整个图像的比例设为w1,其平均灰度设为u1。(4)图像的总平均灰度设为u,类间方差设为S。 假设图片的大小为M*N,图像中像素灰度值小于阈值T的像素个数记为N0,像素灰度大于阈值T的像素个数记为N1。则它们之间的关系如下。

大津法原理(otsu)

大津法原理(otsu)

最大类间方差法(大津法,OTSU)最大类间方差法是由日本学者大津(Nobuyuki Otsu)于1979年提出的,是一种自适应的阈值确定的方法,又叫大津法,简称OTSU 。

它是按图像的灰度特性,将图像分成背景和目标2部分。

背景和目标之间的类间方差越大,说明构成图像的2部分的差别越大,当部分目标错分为背景或部分背景错分为目标都会导致2部分差别变小。

因此,使类间方差最大的分割意味着错分概率最小。

对于图像I(x,y),前景(即目标)和背景的分割阈值记作T ,属于前景的像素点数占整幅图像的比例记为1ω,其平均灰度1μ;背景像素点数占整幅图像的比例为2ω,其平均灰度为2μ。

图像的总平均灰度记为μ,类间方差记为g 。

假设图像的背景较暗,并且图像的大小为M N ⨯,图像中像素的灰度值小于阈值T 的像素个数记作1N ,像素灰度大于阈值T 的像素个数记作2N ,则有:11N M N ω=⨯ (1.1)22N M N ω=⨯ (1.2)12N N M N +=⨯ (1.3)121ωω+= (1.4)1122μμωμω=⨯+⨯ (1.5) 221122()()g ωμμωμμ=⨯-+⨯-(1.6) 将式(1.5)代入式(1.6),得到等价公式:21212()g ωωμμ=⨯⨯- (1.7) 采用遍历的方法得到使类间方差最大的阈值T ,即为所求。

OpenCV 代码:int myOtsu(const IplImage *frame) //大津法求阈值{#define GrayScale 256 //frame 灰度级int width = frame->width;int height = frame->height;int pixelCount[GrayScale]={0};float pixelPro[GrayScale]={0};int i, j, pixelSum = width * height, threshold = 0;uchar* data = (uchar*)frame->imageData;//统计每个灰度级中像素的个数for(i = 0; i < height; i++){for(j = 0;j < width;j++){pixelCount[(int)data[i * width + j]]++;}}//计算每个灰度级的像素数目占整幅图像的比例for(i = 0; i < GrayScale; i++){pixelPro[i] = (float)pixelCount[i] / pixelSum;}//遍历灰度级[0,255],寻找合适的thresholdfloat w0, w1, u0tmp, u1tmp, u0, u1, deltaTmp, deltaMax = 0;for(i = 0; i < GrayScale; i++){w0 = w1 = u0tmp = u1tmp = u0 = u1 = deltaTmp = 0;for(j = 0; j < GrayScale; j++){if(j <= i) //背景部分{w0 += pixelPro[j];u0tmp += j * pixelPro[j];}else //前景部分{w1 += pixelPro[j];u1tmp += j * pixelPro[j];}}u0 = u0tmp / w0;u1 = u1tmp / w1;deltaTmp = (float)(w0 *w1* pow((u0 - u1), 2)) ;if(deltaTmp > deltaMax){deltaMax = deltaTmp;threshold = i;}}return threshold;}参考文献:Nobuyuki Otsu发表的原文"A Threshold Selection Method from Gray-Level Histograms," Systems, Man and Cybernetics, IEEE Transactions on , vol.9, no.1, pp.62-66, Jan. 1979。

Ots算法(大律法或最大类间方差法)

Ots算法(大律法或最大类间方差法)

Otsu算法(大律法或最大类间方差法)一、Otsu最大类间方差法原理利用阈值将原图像分成前景,背景两个图象。

前景:用n1,csum,m1来表示在当前阈值下的前景的点数,质量矩,平均灰度后景:用n2, sum-csum,m2来表示在当前阈值下的背景的点数,质量矩,平均灰度当取最佳阈值时,背景应该与前景差别最大,关键在于如何选择衡量差别的标准,而在otsu算法中这个衡量差别的标准就是最大类间方差(英文简称otsu,这也就是这个算法名字的来源),在本程序中类间方差用sb表示,最大类间方差用fmax 关于最大类间方差法(otsu)的性能:类间方差法对噪音和目标大小十分敏感,它仅对类间方差为单峰的图像产生较好的分割效果。

当目标与背景的大小比例悬殊时,类间方差准则函数可能呈现双峰或多峰,此时效果不好,但是类间方差法是用时最少的。

最大类间方差法(otsu)的公式推导:记t为前景与背景的分割阈值,前景点数占图像比例为w0,平均灰度为u0;背景点数占图像比例为w1,平均灰度为u1。

则图像的总平均灰度为:u=w0*u0+w1*u1。

前景和背景图象的方差:g=w0*(u0-u)*(u0-u)+w1*(u1-u)*(u1-u)=w0*w1*(u0-u1)*(u0-u1),此公式为方差公式。

可参照概率论课本上面的g的公式也就是下面程序中的sb的表达式。

当方差g最大时,可以认为此时前景和背景差异最大,此时的灰度t是最佳阈值sb = w1*w2*(u1-u0)*(u0-u1)算法实现1:unsafe public int GetThreshValue(Bitmap image){BitmapData bd = image.LockBits(new Rectangle(0, 0, image.Width, image.Height), ImageLockMode.WriteOnly, image.PixelFormat);byte* pt = (byte*)bd.Scan0;int[] pixelNum = new int[256]; //图象直方图,共256个点byte color;byte* pline;int n, n1, n2;int total; //total为总和,累计值double m1, m2, sum, csum, fmax, sb; //sb为类间方差,fmax存储最大方差值int k, t, q;int threshValue = 1; // 阈值int step = 1;switch (image.PixelFormat){case PixelFormat.Format24bppRgb:step = 3;break;case PixelFormat.Format32bppArgb:step = 4;break;case PixelFormat.Format8bppIndexed:step = 1;break;}//生成直方图for (int i = 0; i < image.Height; i++){pline = pt + i * bd.Stride;for (int j = 0; j < image.Width; j++){color = *(pline + j * step); //返回各个点的颜色,以RGB表示pixelNum[color]++; //相应的直方图加1}}//直方图平滑化for (k = 0; k <= 255; k++){total = 0;for (t = -2; t <= 2; t++) //与附近2个灰度做平滑化,t值应取较小的值{q = k + t;if (q < 0) //越界处理q = 0;if (q > 255)q = 255;total = total + pixelNum[q]; //total为总和,累计值}//平滑化,左边2个+中间1个+右边2个灰度,共5个,所以总和除以5,后面加0.5是用修正值pixelNum[k] = (int)((float)total / 5.0 + 0.5);}//求阈值sum = csum = 0.0;n = 0;//计算总的图象的点数和质量矩,为后面的计算做准备for (k = 0; k <= 255; k++){//x*f(x)质量矩,也就是每个灰度的值乘以其点数(归一化后为概率),sum为其总和sum += (double)k * (double)pixelNum[k];n += pixelNum[k]; //n为图象总的点数,归一化后就是累积概率}fmax = -1.0; //类间方差sb不可能为负,所以fmax初始值为-1不影响计算的进行n1 = 0;for (k = 0; k < 255; k++) //对每个灰度(从0到255)计算一次分割后的类间方差sb{n1 += pixelNum[k]; //n1为在当前阈值遍前景图象的点数if (n1 == 0) { continue; } //没有分出前景后景n2 = n - n1; //n2为背景图象的点数//n2为0表示全部都是后景图象,与n1=0情况类似,之后的遍历不可能使前景点数增加,所以此时可以退出循环if (n2 == 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;}算法实现2:Otsu算法步骤如下:设图象包含L个灰度级(0,1…,L-1),灰度值为i的的象素点数为Ni ,图象总的象素点数为N=N0+N1+...+N(L-1)。

二维otsu法阈值选择

二维otsu法阈值选择

二维Otsu法是一种图像分割算法,能够自适应地选择图像的阈值。

该算法是在Otsu算法基础上,在二维图像上进行的扩展。

一维Otsu法(也称为最大类间方差法)的基本原理是将一幅灰度图像分成两部分,使得每部分的类间方差最大,从而得到最佳的阈值。

与一维Otsu法不同的是,二维Otsu法从图像的全局信息中选择最佳阈值,因此具有更高的鲁棒性和更好的适应性。

实现二维Otsu法的基本步骤如下:1. 对图像进行灰度处理,将彩色图像转换为灰度图像。

2. 计算图像的直方图,即各灰度级别的像素数目。

3. 计算图像的累积分布函数(CDF),即各灰度级别的像素的累计和。

4. 根据CDF计算各灰度级别的均值和方差。

5. 计算各灰度级别的类间方差,选择最大值对应的灰度级别为阈值,用于将图像分割为前景和背景。

需要注意的是,二维Otsu法的实现较为复杂,计算量较大,因此需要在具体应用中结合实际情况进行调优和优化。

在实现二维Otsu法时,需要注意以下几点:1. 对图像进行预处理,如平滑、滤波和缩放等,以提高算法效率和准确度。

2. 根据图像的特点和实际需求,选择合适的灰度级别数目和区间范围,并进行合适的采样和压缩。

3. 对于大尺寸、高分辨率和复杂场景的图像,可以采用分块处理或多层分割等技术来提高算法效率和准确度。

4. 在计算类间方差时,需要进行有效的数据处理和统计方法,以避免过拟合和低通滤波等问题。

5. 在图像分割后,需要进行后续处理,如形态学运算、噪声消除和轮廓提取等,以得到更精确和完整的分割结果。

总的来说,二维Otsu法是一种非常有效和实用的图像分割算法,可以广泛应用于图像处理、计算机视觉和模式识别等领域。

如果您需要更具体的技术细节和应用案例,建议咨询相关专业人士或参考相关文献。

OSTU最大类间方差

OSTU最大类间方差

OSTU最大类间方差法原理在最小二乘原理基础上推导出来的,适用于双峰的直方图。

利用阈值将原图像分成前景,背景两个部分。

当取最佳阈值时,背景应该与前景差别最大,即方差最大。

OSTU算法找的就是这个最大方差下的阈值。

最大类间方差法的公式推导:记t为前景与背景的分割阈值,前景是所有灰度级大于t的像素点,背景是所有灰度级小于或等于t的像素点。

前景点数占图像比例为w0,前景加权平均灰度为u0;背景点数占图像比例为w1,背景加权平均灰度为u1。

则整个图像的总平均灰度为:u=w0*u0+w1*u1。

前景和背景图象的方差:g(t)=w0*(u0-u)*(u0-u)+w1*(u1-u)*(u1-u)=w0*w1*(u0-u1)*(u0-u1)。

g(t)就是当分割阈值为t时的类间方差表达式。

OSTU算法使得g(t)取得全局最大值,当g(t)为最大时所对应的t称为最佳阈值。

循环求取最大方差即可。

MABLAB代码及详细注释:function ostuimg = imread('Lena.jpg');I_gray=rgb2gray(img);figure,imshow(I_gray);I_double=double(I_gray); %转化为双精度,因为大多数的函数和操作都是基于double的%figure,imshow(I_double);[wid,len]=size(I_gray); %wid为行数,len为列数colorlevel=256; %灰度级hist=zeros(colorlevel,1); %直方图,256×1的0矩阵%threshold=128; %初始阈值%计算直方图,统计灰度值的个数for i=1:widfor j=1:lenm=I_gray(i,j)+1; %因为灰度为0-255所以+1hist(m)=hist(m)+1;endend%直方图归一化hist=hist/(wid*len);%miuT为总的平均灰度,hist[m]代表像素值为m的点个数miuT=0;for m=1:colorlevelmiuT=miuT+(m-1)*hist(m);endxigmaB2=0; %用于保存每次计算的方差,与下次计算的方差比较大小for mindex=1:colorlevelthreshold=mindex-1;omega1=0; %前景点所占比例omega2=0; %背景点所占比例for m=1:threshold-1omega1=omega1+hist(m); %计算前景比例endomega2=1-omega1; %计算背景比例miu1=0; %前景平均灰度比例miu2=0; %背景平均灰度比例%计算前景与背景平均灰度for m=1:colorlevelif mmiu1=miu1+(m-1)*hist(m); %前景平均灰度elsemiu2=miu2+(m-1)*hist(m); %背景平均灰度endend% miu1=miu1/omega1;% miu2=miu2/omega2;%计算前景与背景图像的方差xigmaB21=omega1*(miu1-miuT)^2+omega2*(miu2-miuT)^2;xigma(mindex)=xigmaB21; %保留每次计算的方差%每次计算方差后,与上一次计算的方差比较。

【转】七种常见阈值分割代码(Otsu、最大熵、迭代法、自适应阀值、手动、迭代法、基本全局阈值法)

【转】七种常见阈值分割代码(Otsu、最大熵、迭代法、自适应阀值、手动、迭代法、基本全局阈值法)

【转】七种常见阈值分割代码(Otsu、最⼤熵、迭代法、⾃适应阀值、⼿动、迭代法、基本全局阈值法)⼀、⼯具:VC+OpenCV⼆、语⾔:C++三、原理otsu法(最⼤类间⽅差法,有时也称之为⼤津算法)使⽤的是聚类的思想,把图像的灰度数按灰度级分成2个部分,使得两个部分之间的灰度值差异最⼤,每个部分之间的灰度差异最⼩,通过⽅差的计算来寻找⼀个合适的灰度级别来划分。

所以可以在⼆值化的时候采⽤otsu 算法来⾃动选取阈值进⾏⼆值化。

otsu算法被认为是图像分割中阈值选取的最佳算法,计算简单,不受图像亮度和对⽐度的影响。

因此,使类间⽅差最⼤的分割意味着错分概率最⼩。

设t为设定的阈值。

wo:分开后前景像素点数占图像的⽐例uo:分开后前景像素点的平均灰度w1:分开后被景像素点数占图像的⽐例u1:分开后被景像素点的平均灰度u=w0*u0 + w1*u1 :图像总平均灰度从L个灰度级遍历t,使得t为某个值的时候,前景和背景的⽅差最⼤,则这个 t 值便是我们要求得的阈值。

其中,⽅差的计算公式如下:g=wo * (uo - u) * (uo - u) + w1 * (u1 - u) * (u1 - u)[ 此公式计算量较⼤,可以采⽤: g = wo * w1 * (uo - u1) * (uo - u1) ]由于otsu算法是对图像的灰度级进⾏聚类,so 在执⾏otsu算法之前,需要计算该图像的灰度直⽅图。

迭代法原理:迭代选择法是⾸先猜测⼀个初始阈值,然后再通过对图像的多趟计算对阈值进⾏改进的过程。

重复地对图像进⾏阈值操作,将图像分割为对象类和背景类,然后来利⽤每⼀个类中的灰阶级别对阈值进⾏改进。

图像阈值分割---迭代算法1 .处理流程:1.为全局阈值选择⼀个初始估计值T(图像的平均灰度)。

2.⽤T分割图像。

产⽣两组像素:G1有灰度值⼤于T的像素组成,G2有⼩于等于T像素组成。

3.计算G1和G2像素的平均灰度值m1和m2;4.计算⼀个新的阈值:T = (m1 + m2) / 2;5.重复步骤2和4,直到连续迭代中的T值间的差⼩于⼀个预定义参数为⽌。

大津法求阈值

大津法求阈值

大津法求阈值
大津法求阈值,又称为最大类间方差法或Otsu算法,是一种自动图像阈值分割的统计学方法,由日本图像处理专家Nobuyuki Otsu于1979年提出。

该方法根据灰度直方图计算出合适的阈值,以分隔不同灰度水平的图像。

它被认为是最优二值化的方法,也是目前最流行的图像分割算法之一。

首先,所谓的“大津法求阈值”,是指在图像分割中,采用Otsu的算法来寻找最佳的阈值,以将图像有效分割为前景和背景两部分。

它的主要思想是:通过计算灰度值的类间方差,确定一个最佳的阈值,以此来使得类间方差最大,从而得到最佳的分割效果。

大津法求阈值的具体步骤如下:
(1)将灰度图像像素点按其灰度值从低到高排序,形成灰度直方图;
(2)计算每个灰度级中像素点的累积概率;
(3)从灰度值最小的级开始,依次将每个灰度级作为阈值,计算背景和前景的类间方差;
(4)选取类间方差最大的阈值作为最佳阈值;
(5)将原图像中像素点的灰度值与最佳阈值比较,大于最佳阈值的像素点设为前景,小于最佳阈值的像素点设为背景。

大津法求阈值在图像分割中具有明显的优势:(1)它是一种无人参与的自动化算法,结果更加准确可靠;(2)它可以在不同的图像上获得较高的分割质量;(3)它可以实现快速的计算,不需要太多额外的计算;(4)它可以在不同的图像上获得较高的分割质量。

总而言之,大津法求阈值是一种非常有效的图像分割方法,可以快速有效地将图像分割为前景和背景两部分,从而提高图像处理的效率。

图像二值化阈值选取常用方法汇总

图像二值化阈值选取常用方法汇总

图像二值化阈值选取常用方法最近在公司搞车牌识别的项目,车牌定位后,发现对车牌区域二值化的好坏直接影响后面字符切分的过程,所以就想把常用阈值选取方法做一个总结。

图像二值化阈值选取常用方法:1.双峰法。

2.P 参数法。

3.最大类间方差法(Otsu 、大津法)。

4.最大熵阈值法。

5.迭代法(最佳阈值法)。

1.双峰法在一些简单的图像中,物体的灰度分布比较有规律,背景与目标在图像的直方图各自形成一个波峰,即区域与波峰一一对应,每两个波峰之间形成一个波谷。

那么,选择双峰之间的波谷所代表的灰度值T 作为阈值,即可实现两个区域的分割。

如图1所示。

2.P 参数法当目标与背景的直方图分布有一定重叠时,两个波峰之间的波谷很不明显。

若采用双峰法,效果很差。

如果预先知道目标占整个图像的比例P ,可以采用P 参数法。

P 参数法具体步骤如下:假设预先知道目标占整个图像的比例为P ,且目标偏暗,背景偏亮。

1)、计算图像的直方图分布P(t),t=0,1,.....255。

2)、计算阈值T ,使其满足0()*Tt p t Pm n =-∑最小。

P 参数法一般用于固定分辨率下,目标所占整个图像比例已知的情况。

3.最大类间方差法(Otsu)最大类间方差法是由Otsu 于1979年提出的,是基于整幅图像的统计特性实现阈值的自动选取的,是全局二值化最杰出的代表。

Otsu 算法的基本思想是用某一假定的灰度值t 将图像的灰度分成两组,当两组的类间方差最大时,此灰度值t 就是图像二值化的最佳阈值。

设图像有L 个灰度值,取值范围在0~L-1,在此范围内选取灰度值T ,将图像分成两组G0和G1,G0包含的像素的灰度值在0~T ,G1的灰度值在T+1~L-1,用N 表示图像像素总数,i n 表示灰度值为i 的像素的个数。

已知:每一个灰度值i 出现的概率为/i i p n N =;假设G0和G1两组像素的个数在整体图像中所占百分比为01ϖϖ、,两组平均灰度值为01μμ、,可得概率:00=T ii p ϖ=∑11011L i i T p ωω-=+==-∑平均灰度值:00T i i ipμ==∑111L ii T i p μ-=+=∑图像总的平均灰度值:0011μϖμϖμ=+类间方差:()()()22200110101()g t ωμμωμμωωμμ=-+-=-最佳阈值为:T=argmax(g(t))使得间类方差最大时所对应的t 值。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

Otsu算法(大律法或最大类间方差法)一、Otsu最大类间方差法原理利用阈值将原图像分成前景,背景两个图象。

前景:用n1,csum,m1来表示在当前阈值下的前景的点数,质量矩,平均灰度后景:用n2, sum-csum,m2来表示在当前阈值下的背景的点数,质量矩,平均灰度当取最佳阈值时,背景应该与前景差别最大,关键在于如何选择衡量差别的标准,而在otsu算法中这个衡量差别的标准就是最大类间方差(英文简称otsu,这也就是这个算法名字的来源),在本程序中类间方差用sb表示,最大类间方差用fmax 关于最大类间方差法(otsu)的性能:类间方差法对噪音和目标大小十分敏感,它仅对类间方差为单峰的图像产生较好的分割效果。

当目标与背景的大小比例悬殊时,类间方差准则函数可能呈现双峰或多峰,此时效果不好,但是类间方差法是用时最少的。

最大类间方差法(otsu)的公式推导:记t为前景与背景的分割阈值,前景点数占图像比例为w0,平均灰度为u0;背景点数占图像比例为w1,平均灰度为u1。

则图像的总平均灰度为:u=w0*u0+w1*u1。

前景和背景图象的方差:g=w0*(u0-u)*(u0-u)+w1*(u1-u)*(u1-u)=w0*w1*(u0-u1)*(u0-u1),此公式为方差公式。

可参照概率论课本上面的g的公式也就是下面程序中的sb的表达式。

当方差g最大时,可以认为此时前景和背景差异最大,此时的灰度t是最佳阈值sb = w1*w2*(u1-u0)*(u0-u1)算法实现1:unsafe public int GetThreshValue(Bitmap image){BitmapData bd = image.LockBits(new Rectangle(0, 0, image.Width, image.Height), ImageLockMode.WriteOnly, image.PixelFormat);byte* pt = (byte*)bd.Scan0;int[] pixelNum = new int[256]; //图象直方图,共256个点byte color;byte* pline;int n, n1, n2;int total; //total为总和,累计值double m1, m2, sum, csum, fmax, sb; //sb为类间方差,fmax存储最大方差值int k, t, q;int threshValue = 1; // 阈值int step = 1;switch (image.PixelFormat){case PixelFormat.Format24bppRgb:step = 3;break;case PixelFormat.Format32bppArgb:step = 4;break;case PixelFormat.Format8bppIndexed:step = 1;break;}//生成直方图for (int i = 0; i < image.Height; i++){pline = pt + i * bd.Stride;for (int j = 0; j < image.Width; j++){color = *(pline + j * step); //返回各个点的颜色,以RGB表示pixelNum[color]++; //相应的直方图加1}}//直方图平滑化for (k = 0; k <= 255; k++){total = 0;for (t = -2; t <= 2; t++) //与附近2个灰度做平滑化,t值应取较小的值{q = k + t;if (q < 0) //越界处理q = 0;if (q > 255)q = 255;total = total + pixelNum[q]; //total为总和,累计值}//平滑化,左边2个+中间1个+右边2个灰度,共5个,所以总和除以5,后面加0.5是用修正值pixelNum[k] = (int)((float)total / 5.0 + 0.5);}//求阈值sum = csum = 0.0;n = 0;//计算总的图象的点数和质量矩,为后面的计算做准备for (k = 0; k <= 255; k++){//x*f(x)质量矩,也就是每个灰度的值乘以其点数(归一化后为概率),sum为其总和sum += (double)k * (double)pixelNum[k];n += pixelNum[k]; //n为图象总的点数,归一化后就是累积概率}fmax = -1.0; //类间方差sb不可能为负,所以fmax初始值为-1不影响计算的进行n1 = 0;for (k = 0; k < 255; k++) //对每个灰度(从0到255)计算一次分割后的类间方差sb{n1 += pixelNum[k]; //n1为在当前阈值遍前景图象的点数if (n1 == 0) { continue; } //没有分出前景后景n2 = n - n1; //n2为背景图象的点数//n2为0表示全部都是后景图象,与n1=0情况类似,之后的遍历不可能使前景点数增加,所以此时可以退出循环if (n2 == 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;}算法实现2:Otsu算法步骤如下:设图象包含L个灰度级(0,1…,L-1),灰度值为i的的象素点数为Ni ,图象总的象素点数为N=N0+N1+...+N(L-1)。

灰度值为i的点的概率为:P(i) = N(i)/N.门限t将整幅图象分为暗区c1和亮区c2两类,则类间方差σ是t的函数:σ=a1*a2(u1-u2)^2 (2) 式中,aj 为类cj的面积与图象总面积之比,a1=sum(P(i)) i->t, a2 = 1-a1;uj为类cj的均值,u1 = sum(i*P(i))/a1 0->t, u2 = sum(i*P(i))/a2, t+1->L-1,该法选择最佳门限t^使类间方差最大,即:令Δu=u1-u2,σb = max{a1(t)*a2(t)Δu^2}代码实现:int otsu (IplImage *image, int rows, int cols, int x0, int y0, int dx, int dy, int vvv){unsigned char *np; // 图像指针int thresholdValue=1; // 阈值int ihist[256]; // 图像直方图,256个点int i, j, k; // various countersint n, n1, n2, gmin, gmax;double m1, m2, sum, csum, fmax, sb;// 对直方图置零memset(ihist, 0, sizeof(ihist));gmin=255; gmax=0;// 生成直方图/*for (i = y0 + 1; i < y0 + dy - 1; i++){np = &image[i*cols+x0+1];for (j = x0 + 1; j < x0 + dx - 1; j++){ihist[*np]++;if(*np > gmax) gmax=*np;if(*np < gmin) gmin=*np;np++; /* next pixel}}*/for(j=y0;j<dy;j++){for(i=0;i<dx;i++){unsigned char temp=CV_IMAGE_ELEM(image,uchar,j,i);ihist[temp]++;}}// set up everythingsum = csum = 0.0;n = 0;for (k = 0; k <= 255; k++){sum += (double) k * (double) ihist[k]; // x*f(x) 质量矩n += ihist[k]; //f(x) 质量}if (!n){// if n has no value, there is problemsfprintf (stderr, "NOT NORMAL thresholdValue = 160\n");return (160);}// do the otsu global thresholding methodfmax = -1.0;n1 = 0;for (k = 0; k < 255; k++){n1 += ihist[k];if (!n1) { continue; }n2 = n - n1;if (n2 == 0) { break; }csum += (double) k *ihist[k];m1 = csum / n1;m2 = (sum - csum) / n2;sb = (double) n1 *(double) n2 *(m1 - m2) * (m1 - m2);/**//* bbg: note: can be optimized. */if (sb > fmax) {fmax = sb;thresholdValue = k;}}// at this point we have our thresholding value,debug code to display thresholding valuesif ( vvv & 1 )fprintf(stderr,"# OTSU: thresholdValue = %d gmin=%d gmax=%d\n",thresholdValue, gmin, gmax);return(thresholdValue);}。

相关文档
最新文档