最大类间方差法(otsu)的原理
OpenCV-Python系列之OTSU算法
OpenCV-Python系列之OTSU算法上⼀个教程中,我们谈到了关于图像⼆值化的两种⽅法,⼀种是固定阈值法,另⼀种是⾃适应阈值法,总的来说,⾃适应阈值法在某些⽅⾯要由于固定阈值法,但还没完,这次我们将隆重介绍我们的重量级选⼿,也就是OTSU算法(⼜称为⼤津算法和最⼤类间⽅差法)。
最⼤类间⽅差法是1979年由⽇本学者⼤津提出的,是⼀种⾃适应阈值确定的⽅法,⼜叫⼤津法,简称OTSU,是⼀种基于全局的⼆值化算法,它是根据图像的灰度特性,将图像分为前景和背景两个部分。
当取最佳阈值时,两部分之间的差别应该是最⼤的,在OTSU算法中所采⽤的衡量差别的标准就是较为常见的最⼤类间⽅差。
前景和背景之间的类间⽅差如果越⼤,就说明构成图像的两个部分之间的差别越⼤,当部分⽬标被错分为背景或部分背景被错分为⽬标,都会导致两部分差别变⼩,当所取阈值的分割使类间⽅差最⼤时就意味着错分概率最⼩。
OSTU原理在⼤津算法中,我们穷举搜索能使类内⽅差最⼩的阈值,定义为两个类的⽅差的加权和:权重是被阈值 t分开的两个类的概率,⽽是这两个类的⽅差⼤津证明了最⼩化类内⽅差和最⼤化类间⽅差是相同的:⽤类概率和类均值来表⽰。
类概率⽤阈值为t 的直⽅图计算:⽽类均值为:类概率和类均值可以迭代计算,⼤津算法得出了0:1范围上的⼀个阈值。
这个阈值⽤于图像中出现的像素强度的动态范围。
例如,若图像只包含155到255之间的像素强度,⼤津阈值0.75会映射到灰度阈值230(⽽不是192,因为图像包含的像素不是0–255全范围的)。
对于图像I(x,y),前景(即⽬标)和背景的分割阈值记作T,属于前景的像素点数占整幅图像的⽐例记为ω0,其平均灰度µ0;背景像素点数占整幅图像的⽐例为ω1,其平均灰度为µ1。
图像的总平均灰度记为µ,类间⽅差记为g。
假设图像的背景较暗,并且图像的⼤⼩为M×N,图像中像素的灰度值⼩于阈值T的像素个数记作N0,像素灰度⼤于阈值T的像素个数记作N1,则有: (1) ω0=N0/ (M×N) (2) ω1=N1/ (M×N) (3) N0 + N1 = M×N (4) ω0 + ω1 = 1 (5) µ = ω0 * µ0 + ω1 * µ1 (6) g = ω0 * (µ0 - µ)2 + ω1 * (µ1 - µ)2将式(5)代⼊式(6),得到等价公式: (7) g = ω0 *ω1 * (µ0 - µ1)2采⽤遍历的⽅法得到使类间⽅差g最⼤的阈值T。
Otsu算法(大律法或最大类间方差法)
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)最大类间方差法是由日本学者大津(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。
OTSU算法
图像二值化----otsu(最大类间方差法、大津算法)
最大类间方差法是由日本学者大津于1979年提出的,是一种自适应的阈值确定的方法,又叫大津法,简称OTSU。
它是按图像的灰度特性,将图像分成背景和目标两部分。
背景和目标之间的类间方差越大,说明构成图像的两部分的差别越大,当部分目标错分为背景或部分背景错分为目标都会导致两部分差别变小。
因此,类间方差最大的分割意味着错分概率最小。
OTSU被认为是图像分割中阈值选取的最佳算法,计算简单,不受图像亮度和对比度的影响,因此在数字图像处理上得到了广泛的应用。
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}。
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)
最大类间方差法是由日本学者大津于1979年提出的,是一种自适应的阈值确定的方法,又叫大津法,简称OTSU。
它是按图像的灰度特性,将图像分成背景和目标两部分。
背景和目标之间的类间方差越大,说明构成图像的两部分的差别越大, 当部分目标错分为背景或部分背景错分为目标都会导致两部分差别变小。
因此,使类间方差最大的分割意味着错分概率最小。
function ostu,filequeryStatus = QUERY_IMAGE(file, fileInfo)if queryStatus eq 0 then beginResult = DIALOG_MESSAGE('图像格式不可识别!',/error,title='警告') return,0endifif (fileInfo.CHANNELS ne 1) then beginResult = DIALOG_MESSAGE('图像格式必须为8bit',/error,title='警告') return,0endifimgSize = fileInfo.dimensionsimg=READ_IMAGE(file)p=HISTOGRAM(img)p=p/(imgSize[0]*imgSize[1]*1.0)D=0.0T0=0 ;阈值for T=0,255 do beginp0=0.0 & m0=0for i=0,T do beginp0=p0+p[i]m0=m0+i*p[i]endform0=m0/p0p1=0.0 & m1=0for i=T+1,255 do beginp1=p1+p[i]m1=m1+i*p[i]endform1=m1/p1m=p0*m0+p1*m1D01=p0*(m0-m)^2+p1*(m1-m)^2if (D lt D01) then beginD=D01T0=Tendifendforprint,'ostu法阈值:'+strtrim(T0,2)img [WHERE (img le T0)] = 0img [WHERE (img gt T0)] = 255return, imgend;--------------------pro ostu_test,imagefileDEVICE, DECOMPOSED=1; 获取本程序所在文件路径RootDir = Sourceroot()if n_elements(imagefile) eq 0 then imagefile='man' file=RootDir+imagefile+'.bmp'imgSize = fileInfo.dimensionsimg=READ_IMAGE(file)ostuimg=ostu(file)WINDOW, /free, XSIZE = imgSize[0], YSIZE = imgSize[1] TV, imgend。
OTSU算法学习OTSU公式证明
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 =1- 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*w0a2 = 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初等代数运算的讲解2 关于最⼤类间⽅差法(otsu)的性能:类间⽅差法对噪⾳和⽬标⼤⼩⼗分敏感,它仅对类间⽅差为单峰的图像产⽣较好的分割效果。
当⽬标与背景的⼤⼩⽐例悬殊时,类间⽅差准则函数可能呈现双峰或多峰,此时效果不好,但是类间⽅差法是⽤时最少的。
3 代码实现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;}//⽣成直⽅图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;}参考了这篇⽂章4 ⼆维otsu算法下图是⼆维otsu的⽴体图,是对右边的A进⾏⼆维直⽅图统计得到的图像, 遍历区域为5*5.这是对应的matlab代码%统计⼆维直⽅图 i 当前点的亮度 j n*n邻域均值亮度function hist2 = hist2Function(image, n)%初始化255*2565矩阵hist2 = zeros(255,255);[height, width]= size(image);for i =1:heightfor j =1:widthdata = image(i,j);tempSum =0.0;for l =-n:1:nfor m =-n:1:nx = i + l;y = j+m;if x <1x =1;elseif x > widthx = width;endif y <1y =1;elseif y > heighty = height;endtempSum = tempSum + double(image(y,x));endendtempSum = tempSum /((2*n+1)*(2*n+1));hist2(data,floor(tempSum))= hist2(data,floor(tempSum))+1;endend%加载图像imagea = imread('a.bmp');%显⽰图像%imshow(imagea);%显⽰直⽅图%figure;imhist(imagea);%计算⼆维直⽅图hist2 = hist2Function(imagea,2);%显⽰⼆维直⽅图[x,y]=meshgrid(1:1:255);mesh(x,y,hist2)<灰度图象的⼆维Otsu⾃动阈值分割法.pdf> 这篇⽂章讲解的不错.⽂章这⾥有下载下⾯⽤数学语⾔表达⼀下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)]这⾥是代码实现.出⾃这篇⽂章:int histogram[256][256];double p_histogram[256][256];double Pst_0[256][256];//Pst_0⽤来存储概率分布情况double Xst_0[256][256];//存储x⽅向上的均值⽮量int OTSU2d(IplImage * src){int height = src->height;int width = src->width;long pixel = height * width;int i,j;for(i =0;i <256;i++)//初始化直⽅图for(j =0; j <256;j++)histogram[i][j]=0;}IplImage * temp = cvCreateImage(cvGetSize(src),8,1);cvSmooth(src,temp,CV_BLUR,3,0);for(i =0;i < height;i++)//计算直⽅图{for(j =0; j < width;j++){int data1 = cvGetReal2D(src,i,j);int data2 = cvGetReal2D(temp,i,j);histogram[data1][data2]++;}}for(i =0; i <256;i++)//直⽅图归⼀化for(j =0; j <256;j++)p_histogram[i][j]=(histogram[i][j]*1.0)/(pixel*1.0);Pst_0[0][0]= p_histogram[0][0];for(i =0;i <256;i++)//计算概率分布情况for(j =0;j <256;j++){double temp =0.0;if(i-1>=0)temp = temp + Pst_0[i-1][j];if(j-1>=0)temp = temp + Pst_0[i][j-1];if(i-1>=0&& j-1>=0)temp = temp - Pst_0[i-1][j-1];temp = temp + p_histogram[i][j];Pst_0[i][j]= temp;}Xst_0[0][0]=0* Pst_0[0][0];for(i =0; i <256;i++)//计算x⽅向上的均值⽮量for(j =0; j <256;j++){double temp =0.0;if(i-1>=0)temp = temp + Xst_0[i-1][j];if(j-1>=0)temp = temp + Xst_0[i][j-1];if(i-1>=0&& j-1>=0)temp = temp - Xst_0[i-1][j-1];temp = temp + i * p_histogram[i][j];Xst_0[i][j]= temp;}double Yst_0[256][256];//存储y⽅向上的均值⽮量Yst_0[0][0]=0* Pst_0[0][0];for(i =0; i <256;i++)//计算y⽅向上的均值⽮量for(j =0; j <256;j++){double temp =0.0;if(i-1>=0)temp = temp + Yst_0[i-1][j];if(j-1>=0)temp = temp + Yst_0[i][j-1];if(i-1>=0&& j-1>=0)temp = temp - Yst_0[i-1][j-1];temp = temp + j * p_histogram[i][j];Yst_0[i][j]= temp;}int threshold1;int threshold2;double variance =0.0;double maxvariance =0.0;for(i =0;i <256;i++)//计算类间离散测度for(j =0;j <256;j++){longdouble p0 = Pst_0[i][j];longdouble v0 = pow(((Xst_0[i][j]/p0)-Xst_0[255][255]),2)+ pow(((Yst_0[i][j]/p0)-Yst_0[255][255]),2);longdouble p1 = Pst_0[255][255]-Pst_0[255][j]-Pst_0[i][255]+Pst_0[i][j];longdouble vi = Xst_0[255][255]-Xst_0[255][j]-Xst_0[i][255]+Xst_0[i][j];longdouble vj = Yst_0[255][255]-Yst_0[255][j]-Yst_0[i][255]+Yst_0[i][j];longdouble v1 = pow(((vi/p1)-Xst_0[255][255]),2)+pow(((vj/p1)-Yst_0[255][255]),2);variance = p0*v0+p1*v1;if(variance > maxvariance){maxvariance = variance;threshold1 = i;threshold2 = j;}}//printf("%d %d",threshold1,threshold2);return(threshold1+threshold2)/2;}总结: ⼆维otsu算法得到⼀个阈值,然后对图像做⼆值化.仍然不能解决光照不均匀⼆值化的问题.⽐⼀维otsu效果好⼀些,但不是很明显.这个算法的亮点在于考虑的点的附近区域的均值.。
一种改进的火焰图像分割方法
一种改进的火焰图像分割方法摘要:在火灾图像识别算法中,将火焰图像从背景中分离出来是识别过程的前提条件和必要环节。
从目前应用情况来看,最大类间方差法(也称Otsu法)是比较简洁有效的方法。
该方法属于阈值选取方法,其特点是算法比较简单,适于实时处理,其局限性在于对图像的“双峰直方图”过于依赖。
针对该方法上述的缺点和不足,提出了一种新型的基于灰度积分投影法的火焰图像分割及定位方法。
实验证明,该算法不但能正确地将火焰图像从背景中快速分离出来,而且可迅速定位火焰的中心位置,可以为动态识别火焰图像提供重要的判别依据。
关键词:图像分割灰度积分投影最大类间方差法火焰检测在现有的火灾识别算法中,将火焰图像与背景图像进行准确有效地分离一直是火灾监控中的关键技术。
只有将火焰与背景图像相分离,并对其特性做进一步的分析,才能对火灾是否发生做出正确的判断。
还可以根据火焰图像像素的增加对火势蔓延做出正确的分析和评估。
因此,基于火焰特点的图像分割算法就显得格外重要。
目前,基于图像灰度或饱和度的直方图分析法是最为常用的方法。
但这种方法受双峰直方图这一条件的限制,对有的图像效果不理想。
此外,直方图法只能显示图像的颜色信息,无法体现图像的空间信息。
在如果能找到一种方法,既能判断火焰图像的尖角位置,又能有效地实现火焰图像与背景的分离,且计算量不大,那么这种方法无疑是比较理想的。
本文利用灰度积分投影法,先确定出火焰图像火苗最高处的水平坐标位置,再从这一列上按搜索法取一片区域像素的平均值作为二值化的阈值,可实现火焰图像的分割,同时这也符合人们的分类习惯。
这样做的的好处是,整个运算过程只有一次对整个图像的遍历操作,大大减少了运算时间。
其次,在抽取火焰图像同时可确定火焰的尖角位置,为后面的识别提供必要的信息。
实验证明,该方法具有运算速度快、定位准确、适用范围广等特点。
1 最大类间方差法简介最大类间方差法是一种常用的图像分割方法,该方法是Otsu在1979年提出的基于自适应阈值分割方法。
otsu 双阈值算法
otsu 双阈值算法Otsu双阈值算法是一种常用的图像分割算法,通过自适应选取合适的阈值,将图像分割为前景和背景。
本文将介绍Otsu双阈值算法的原理和应用。
一、算法原理Otsu双阈值算法是由日本学者大津秀一于1979年提出的。
该算法基于图像的灰度直方图,通过最大类间方差的准则确定两个阈值,将图像分为三个部分:背景、前景和中间部分。
具体步骤如下:1. 计算图像的灰度直方图,统计每个灰度级别的像素数量。
2. 计算总体均值μ和总体方差σ^2。
3. 遍历所有可能的阈值t,计算背景和前景的像素数量和均值。
4. 根据公式计算类间方差σ_b^2 = w_0 * w_1 * (μ_0 - μ_1)^2,其中w_0和w_1分别为背景和前景的像素比例,μ_0和μ_1分别为背景和前景的均值。
5. 找到类间方差最大的阈值作为分割阈值。
6. 根据分割阈值将图像分为背景、前景和中间部分。
二、算法应用Otsu双阈值算法在图像处理领域有广泛的应用,主要用于图像分割和目标提取。
以下是算法在实际应用中的几个示例:1. 血管分割:在医学图像处理中,通过Otsu双阈值算法可以实现血管分割,将血管和其他组织分割出来,提取出感兴趣的血管区域。
2. 文字识别:在文字识别中,Otsu双阈值算法可以将文字和背景分割开,提高文字识别的准确性和效果。
3. 目标检测:在目标检测中,Otsu双阈值算法可以将目标物体和背景分割开,提取出目标物体的特征,用于后续的目标识别和分类。
4. 图像增强:在图像增强中,Otsu双阈值算法可以将图像分割为背景、前景和中间部分,对不同部分的像素进行不同的增强处理,提高图像的质量和清晰度。
总结:Otsu双阈值算法是一种简单而有效的图像分割算法,通过自适应选取阈值,将图像分割为背景、前景和中间部分。
该算法在图像处理和计算机视觉领域有广泛的应用,可以用于血管分割、文字识别、目标检测和图像增强等方面。
通过深入理解和应用Otsu双阈值算法,可以提高图像处理的效果和准确性,为后续的图像分析和处理提供有力支持。
user最大类间方差方法选择阈值进行分割相关概念、原理、数学基础及算法
最大类间方差法(OTSU算法)是一种常用的图像分割方法,它通过计算图像的类间方差来确定分割阈值。
以下是关于最大类间方差法选择阈值进行分割的相关概念、原理、数学基础及算法的简要介绍:
1.概念:
最大类间方差法是一种基于全局的二值化算法,它根据图像的灰度特性,将图像分为前景和背景两个部分。
当取最佳阈值时,两部分之间的差别应该是最大的。
2.原理:
最大类间方差法的原理是:对图像的灰度级直方图进行标准化处理,得到一个概率分布。
以灰度级k为阈值,可将该图像中的像素块二分为两大类C0和C1(背景和前景,反之亦然)。
其中,C0表示灰度级在范围[0, 1, ..., k-1]的像素集合;C1表示灰度级在范围[k, k+1, ..., L-1]的像素集合。
背景和前景之间的类间方差如果越大,就说明构成图像的两个部分之间的差别越大,当部分前景错分为背景或部分背景错分为前景都会导致两部分差别变小。
因此,使类间方差最大的分割意味着错分概率最小。
3.数学基础:
最大类间方差法的数学基础是概率分布和方差。
通过计算灰度级直方图,可以得到图像的概率分布。
然后,通过计算不同阈值下的类间方差,选择使类间方差最大的阈值作为最佳分割阈值。
4.算法:
最大类间方差法的算法包括以下步骤:
(1)对图像的灰度级直方图进行标准化处理,得到一个概率分布。
(2)遍历所有可能的阈值,计算每个阈值下的类间方差。
(3)选择使类间方差最大的阈值作为最佳分割阈值。
(4)根据最佳分割阈值将图像二分为前景和背景两个部分。
以上是关于最大类间方差法选择阈值进行分割的相关概念、原理、数学基础及算法的简要介绍。
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、最⼤熵、迭代法、⾃适应阀值、⼿动、迭代法、基本全局阈值法)⼀、⼯具: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值间的差⼩于⼀个预定义参数为⽌。
最大类间方差法
最大类间方差法背景提出。
从大津法的原理上来讲,该方法又称作最大类间方差法,因为按照大津法求得的阈值进行图像二值化分割后,前景与背景图像的类间方差最大。
方差:它是按图像的灰度特性,将图像分成背景和前景两部分。
因方差是灰度分布均匀性的一种度量,背景和前景之间的类间方差越大,说明构成图像的两部分的差别越大,当部分前景错分为背景或部分背景错分为前景都会导致两部分差别变小。
优点:计算简单,方便,不受图像的亮度的影响,在简单双峰场景中能进行快速分割缺点:噪声的干扰大,当图像没有典型的双峰时,不能够精确分割,对于多峰图像则失去效果。
应用:医学影像分割,目标识别等,常和其它算法结合使用基本原理:OPENCV实现:#include<opencv2/opencv.hpp>#include<vector>#include<iostream>using namespace std;using namespace cv;void otsu(Mat input,Mat&output,int&thres){const int Grayscale = 256;int width = input.cols;int height = input.rows;double Graystatistics[Grayscale] = { 0 };for (int i = 0; i < height; i++){for (int j = 0; j < width;j++){int Grayvalue = input.at<uchar>(i, j); Graystatistics[Grayvalue]++;//直方图统计 }}double allnum = width height;double Pi[Grayscale] = { 0 };//单个个灰度的概率 double P[Grayscale] = { 0 };//累计灰度概率double Mi[Grayscale] = { 0 };//累计灰度平均和 double Psum = 0;double cumgray = 0;for (int i = 0; i < Grayscale; i++){Pi[i] = Graystatistics[i] / allnum;P[i] = Pi[i] + Psum;Psum = P[i];Mi[i] = cumgray + (double)i Pi[i];cumgray = Mi[i];}//计算类间方差double var = 0;thres = 0;for (int i = 0; i < Grayscale; i++){double fenzi = (Mi[Grayscale - 1] P[i] - Mi[i]) (Mi[Grayscale - 1] P[i] - Mi[i]);double fenmu = P[i] (1 - P[i]);double vau = fenzi / fenmu;if (vau > var){var = vau;thres = i;}}cout << thres << endl;input.copyTo(output);for (int i = 0; i < height; i++){for (int j = 0; j < width; j++){int value = output.at<uchar>(i, j);if (value >thres){output.at<uchar>(i, j) = 255;}else{output.at<uchar>(i, j) = 0;}}}}int main({Mat a = imread("1.bmp");cvtColor(a, a, COLOR_RGB2GRAY);Mat b;int th = 0;otsu(a, b, th);int Otsu1 = cv::threshold(a, b, 0, 255, THRESH_OTSU +THRESH_BINARY);cout << Otsu1 << endl;imshow("1", b);return 0;}opencv接口:double threshold(InputArray src, OutputArray dst, double thresh, double maxval, int type)效果:。
求阈值最佳方法
OTSU算法是由日本学者OTSU于1979年提出的一种对图像进行二值化的高效算法。
1. OTSU算法原理简介对于一幅图像,设当前景与背景的分割阈值为t时,前景点占图像比例为w0,均值为u0,背景点占图像比例为w1,均值为u1。
则整个图像的均值为u = w0*u0+w1*u1。
建立目标函数g(t)=w0*(u0-u)^2+w1*(u1-u)^2,g(t)就是当分割阈值为t时的类间方差表达式。
OTSU算法使得g(t)取得全局最大值,当g(t)为最大时所对应的t称为最佳阈值。
OTSU算法又称为最大类间方差法。
2.OTSU算法例程下面是OSTU算法的C语言代码及其测试,代码基于opencv。
[cpp]view plaincopy1.#include <cv.h>2.#include <highgui.h>3.4.int otsu(IplImage *image)5.{6. assert(NULL != image);7.8.int width = image->width;9.int height = image->height;10.int x=0,y=0;11.int pixelCount[256];12.float pixelPro[256];13.int i, j, pixelSum = width * height, threshold = 0;14.15. uchar* data = (uchar*)image->imageData;16.17.//初始化18.for(i = 0; i < 256; i++)19. {20. pixelCount[i] = 0;21. pixelPro[i] = 0;22. }23.24.//统计灰度级中每个像素在整幅图像中的个数25.for(i = y; i < height; i++)26. {27.for(j = x;j <width;j++)28. {29. pixelCount[data[i * image->widthStep + j]]++;30. }31. }32.33.34.//计算每个像素在整幅图像中的比例35.for(i = 0; i < 256; i++)36. {37. pixelPro[i] = (float)(pixelCount[i]) / (float)(pixelSum);38. }39.40.//经典ostu算法,得到前景和背景的分割41.//遍历灰度级[0,255],计算出方差最大的灰度值,为最佳阈值42.float w0, w1, u0tmp, u1tmp, u0, u1, u,deltaTmp, deltaMax = 0;43.for(i = 0; i < 256; i++)44. {45. w0 = w1 = u0tmp = u1tmp = u0 = u1 = u = deltaTmp = 0;46.47.for(j = 0; j < 256; j++)48. {49.if(j <= i) //背景部分50. {51.//以i为阈值分类,第一类总的概率52. w0 += pixelPro[j];53. u0tmp += j * pixelPro[j];54. }55.else//前景部分56. {57.//以i为阈值分类,第二类总的概率58. w1 += pixelPro[j];59. u1tmp += j * pixelPro[j];60. }61. }62.63. u0 = u0tmp / w0; //第一类的平均灰度64. u1 = u1tmp / w1; //第二类的平均灰度65. u = u0tmp + u1tmp; //整幅图像的平均灰度66.//计算类间方差67. deltaTmp = w0 * (u0 - u)*(u0 - u) + w1 * (u1 - u)*(u1 - u);68.//找出最大类间方差以及对应的阈值69.if(deltaTmp > deltaMax)70. {71. deltaMax = deltaTmp;72. threshold = i;73. }74. }75.//返回最佳阈值;76.return threshold;77.}78.79.int main(int argc, char* argv[])80.{81. IplImage* srcImage = cvLoadImage("D:\\technology\\CV\\Database\\image\\rice.png",0);82. assert(NULL != srcImage);83.84. cvNamedWindow("src");85. cvShowImage("src",srcImage);86.87. IplImage* biImage = cvCreateImage(cvGetSize(srcImage),8,1);88.89.//计算最佳阈值90.int threshold = otsu(srcImage);91.//对图像二值化92. cvThreshold(srcImage,biImage,threshold,255,CV_THRESH_BINARY);93.94. cvNamedWindow("binary");95. cvShowImage("binary",biImage);96.97. cvWaitKey(0);98.99. cvReleaseImage(&srcImage);100. cvReleaseImage(&biImage);101. cvDestroyWindow("src");102. cvDestroyWindow("binary");103.104.return 0;105.}。
最大类间方差法阈值初值
最大类间方差法阈值初值最大类间方差法(Otsu算法)是图像处理中常用的一种阈值分割方法,通过将图像分割成两个类别,使类别内部的方差最小,不同类别之间的方差最大,以此确定一个最佳阈值。
而确定最大类间方差阈值的初值,则是这个方法中比较重要的一环。
下面将围绕“最大类间方差法阈值初值”进行讲解,具体步骤如下:1. 计算灰度级概率分布函数首先,我们需要计算图像的灰度级概率分布函数 P(i),其定义为每个像素灰度级 i 在整幅图像中的出现概率。
可以用下式进行计算: P(i) = n(i) / N其中,n(i) 为灰度级为 i 的像素数目,N 为整幅图像像素数目。
2. 计算灰度平均值和全局灰度平均值灰度平均值μ(T) 是指图像像素灰度级的平均值,全局灰度平均值μ(Total) 是整幅图像所有像素灰度值的平均值。
可以用下式进行计算:μ(T) = Σ[i=0, T]i * P(i) / w(T)μ(Total) = Σ[i=0, L]i * P(i)其中,T 为阈值,L 为最大的灰度级数目。
3. 计算类内方差类内方差σ1²(T) 是指灰度值小于等于 T 的像素的方差,类内方差σ2²(T) 是指灰度值大于 T 的像素的方差。
可以用下式进行计算:σ1²(T) = Σ[i=0, T](i - μ1(T))² * P(i) / w1(T)σ2²(T) = Σ[i=T+1, L](i - μ2(T))² * P(i) / w2(T)其中,μ1(T) 和μ2(T) 是灰度值小于等于 T 和大于 T 的像素灰度级的平均值,w1(T) 和 w2(T) 则是灰度值小于等于 T 和大于T 的像素数量。
4. 计算类间方差类间方差σ(T)² 是指灰度值小于等于 T 和灰度值大于 T 的像素之间的方差,可以用下式进行计算:σ(T)² = w1(T) * w2(T) * (μ1(T) - μ2(T))²5. 确定最大类间方差阈值最大类间方差阈值即为使类间方差σ(T)² 最大的阈值 T,可以先将所有灰度级都作为初值进行计算,然后根据所求得的最大值确定最优阈值。
最大类间方差法
最大类间方差法是由日本学者大津于1979年提出的,是一种自适应的阈值确定的方法,又叫大津法,简称OTSU。
它是按图像的灰度特性,将图像分成背景和目标2部分。
背景和目标之间的类间方差越大,说明构成图像的2部分的差别越大,当部分目标错分为背景或部分背景错分为目标都会导致2部分差别变小。
因此,使类间方差最大的分割意味着错分概率最小。
对于图像I(x,y),前景(即目标)和背景的分割阈值记作T,属于前景的像素点数占整幅图像的比例记为ω0,其平均灰度μ0;背景像素点数占整幅图像的比例为ω1,其平均灰度为μ1。
图像的总平均灰度记为μ,类间方差记为g。
假设图像的背景较暗,并且图像的大小为M×N,图像中像素的灰度值小于阈值T的像素个数记作N0,像素灰度大于阈值T的像素个数记作N1,则有: ω0=N0/ M×N (1)ω1=N1/ M×N (2)N0+N1=M×N (3)ω0+ω1=1 (4)μ=ω0*μ0+ω1*μ1 (5)g=ω0(μ0-μ)^2+ω1(μ1-μ)^2 (6)将式(5)代入式(6),得到等价公式: g=ω0ω1(μ0-μ1)^2 (7)采用遍历的方法得到使类间方差最大的阈值T,即为所求。
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}OTSU方法计算图像二值化的自适应阈值int otsu (unsigned char *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++;}}// set up everythingsum = csum = 0.0;n = 0;for (k = 0; k <= 255; k++) {sum += (double) k * (double) ihist[k];n += ihist[k];}if (!n) {// if n has no value, there is problems...fprintf (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); 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);}///////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////另外一个///////////////////////////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////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为总和,累计值}pixelNum[k] = (int)((float)total / 5.0 + 0.5); //平滑化,左边2个+中间1个+右边2个灰度,共5个,所以总和除以5,后面加0.5是用修正值}//求阈值sum = csum = 0.0;n = 0;//计算总的图象的点数和质量矩,为后面的计算做准备for (k = 0; k <= 255; k++){sum += (double)k * (double)pixelNum[k]; //x*f(x)质量矩,也就是每个灰度的值乘以其点数(归一化后为概率),sum为其总和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为背景图象的点数if (n2 == 0) { break; } //n2为0表示全部都是后景图象,与n1=0情况类似,之后的遍历不可能使前景点数增加,所以此时可以退出循环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;}。
otsu
传统的最大类间方差法 ( Otsu 法) 是基于一维直方图的, 只考虑了像素点本身的灰度值,而没有考虑像素点的空 间信息, 所以采集图像时混入的噪声会影响分割效果。 基于二维直方图的分割方法是在原来一维灰度信息的基 础上又引入该像素点的邻域平均灰度信息,利用图像的 空间信息来提高 Otsu 分割算法的抗噪能力。
➢ 将二维二值推广到多阈值。
实图像分割方法研究
原文链接: /KCMS/detail/detail.aspx?QueryID=1&CurRe c=1&recid=&filename=NJYJ201503015&dbname=CJFDTEMP&db code=CJFQ&pr=&urlid=&yx=&v=MDY5MDBLeWZTWkxHNEg5VE1 ySTlFWVlSOGVYMUx1eFlTN0RoMVQzcVRyV00xRnJDVVJMNmVad VJyRnlEbVViM08=
区域 A 和区域 B 的像素灰度均值矢量分别为
通常, 远离直方图对角线的概率可以忽略不计, 二维直方图上总的均值矢量为
区域 A 和区域 B 类间的距离测度函数为
取使 d( S,T) 为最大时对应的阈值便是最佳阈值( S, T) , 确定出最佳阈值后对图像进行二值化处理 。
算法的复杂度? C和D在对角线附近毫无联系?
略, 势必会给阈值的选择带来误差; 如果将所有的点都计算在内 ,又会 增大计算量 。
与对角线平行的两条直线方程为
过阈值分割矢量点 ( S,T) 与对角线垂直的直线 作为目标和背景的分界线, 其直线方程为
此垂线与两条和对角线相平行的直线将直方图重新 划分为如图 3 所示的 C0 、 C1 、 D0 、 D1 4四个区 域, 其中 区域 C0 代表目 标物体, 区域 C1 代表背景区域, 区域D0 和 D1 表示可能的边界点和噪声点。
最大类间方差法(otsu)的原理
在网上很多地方都可以找到,但是我发觉似乎都是一样,而且一点注释都没有,如果光拿来用当然可以了,可是用一个算法不搞清楚里面的数学是件很遗憾的事情,我把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最大时,可以认为此时前景和背景差异最大,也就是此时的灰度是最佳阈值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为总和,累计值}pixelNum[k] = (int)((float)total / 5.0 + 0.5); //平滑化,左边2个+中间1个+右边2个灰度,共5个,所以总和除以5,后面加0.5是用修正值}//求阈值sum = csum = 0.0;n = 0;//计算总的图象的点数和质量矩,为后面的计算做准备for (k = 0; k <= 255; k++){sum += (double)k * (double)pixelNum[k]; //x*f(x)质量矩,也就是每个灰度的值乘以其点数(归一化后为概率),sum为其总和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为背景图象的点数if (n2 == 0) { break; } //n2为0表示全部都是背景图象,与n1=0情况类似,之后的遍历不可能使前景点数增加,所以此时可以退出循环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();如有侵权请联系告知删除,感谢你们的配合!。
kapur 熵和 otsu 最大类间方差法作为目标函数
kapur 熵和 otsu 最大类间方差法作为目标函数Kapur熵和Otsu的最大类间方差法是两种常用的图像阈值分割方法,它们都可以作为目标函数来优化图像分割的效果。
Kapur熵是一种基于信息论的阈值选择方法,其基本思想是通过计算图像中不同灰度级像素的熵来选择最优阈值。
在图像中,像素的灰度值可以看作是随机变量,像素值的分布情况可以反映图像的信息内容。
Kapur熵通过计算不同灰度级像素的熵,找到一个最优阈值,使得分割后的前景和背景像素之间的信息差异最大。
因此,Kapur熵可以作为目标函数来优化图像分割的效果。
Otsu的最大类间方差法也是一种常用的阈值分割方法,其基本思想是通过迭代计算不同阈值下的类间方差,找到一个最优阈值,使得前景和背景像素之间的类间方差最大。
Otsu的最大类间方差法可以自动确定最优阈值,避免了手动选择的困难,并且对于不同灰度级别的图像都可以取得较好的分割效果。
因此,Otsu的最大类间方差法也可以作为目标函数来优化图像分割的效果。
总的来说,Kapur熵和Otsu的最大类间方差法都可以作为目标函数来优化图像分割的效果。
在实际应用中,可以根据具体的问题和数据选择合适的目标函数,以获得更好的图像分割效果。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 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)*(u1u)=w0*w1*(u0-u1)*(u0-u1),此公式为方差公式,可参照概率论课本 上面的g的公式也就是下面程序中的sb的表达式 当方差g最大时,可以认为此时前景和背景差异最大,也就是此时的灰 度是最佳阈值 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个点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值应取较小 的值 {
间方差 if (sb > fmax) //如果算出的类间方差大于前一次算出的类间方差 { fmax = sb; //fmax始终为最大类间方差(otsu) threshValue = k; //取最大类间方差时对应的灰度的k就是最佳阈值 } } image.UnlockBits(bd); image.Dispose();
q = k + t; if (q < 0) //越界处理 q = 0; if (q > 255) q = 255; total = total + pixelNum[q]; //total为总和,累计值 } pixelNum[k] = (int)((float)total / 5.0 + 0.5); //平滑化,左边2 个+中间1个+右边2个灰度,共5个,所以总和除以5,后面加0.5是用修 正值 } //求阈值 sum = csum = 0.0; n = 0; //计算总的图象的点数和质量矩,为后面的计算做准备 for (k = 0; k <= 255; k++) { sum += (double)k * (double)pixelNum[k]; //x*f(x)质量矩,也就是 每个灰度的值乘以其点数(归一化后为概率),sum为其总和 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为背景图象的点数 if (n2 == 0) { break; } //n2为0表示全部都是背景图象,与n1=0情 况类似,之后的遍历不可能使前景点数增加,所以此时可以退出循环 csum += (double)k * pixelNum[k]; //前景的“灰度的值*其点数”的 总和 m1 = csum / n1; //m1为前景的平均灰度 m2 = (sum - csum) / n2; //m2为背景的平均灰度 sb = (double)n1 * (double)n2 * (m1 - m2) * (m1 - m2); //sb为类