最大类间方差法

最大类间方差法是由日本学者大津于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)

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}

代码实现:

```

void CopencvDlg::threshold(IplImage *src,IplImage*temp_src)

{

    int thresol[8];//图像分成8部分,各部分的阈值

    int height=src->height;

    int width=src->width;

    int ceil_height=height/4;

    int ceil_width=width/2;

    IplImage*srcdst=cvCreateImage(cvSize(ceil_width,ceil_height),IPL_DEPTH_8U,src->nChannels);

    for (int i=0;i<2;i++)

    {

        for (int j=0;j<4;j++)

        {

            cvSetImageROI(src ,cvRect(i*ceil_width,j*ceil_height,ceil_width,ceil_height));//选定各个区域

            cvCopy(src,srcdst,0);

            cvResetImageROI(src);

            thresol[i*4+j]=Otsu(srcdst);//otsu阈值分割,返回值为各部分的阈值

        }

    }

    cvSet(temp_src,cvScalarAll(0),0);

    int step=src->widthStep; 

    uchar* data_src=(uchar *)src->imageData; 

    uchar* data_dst=(uchar *)temp_src->imageData;

    //根据计算的阈值对图像进行二值化

    for (int t=0;t<4;t++)

    {

        for (int i=0;i<ceil_width;i++)

        {

            for (int j=0;j<ceil_height;j++)

            {

                if (data_src[j*step+t*ceil_height*step+i]>thresol[t])

                {

                    data_dst[j*step+t*ceil_height*step+i]=255;

                }

                else

                    data_dst[j*step+t*ceil_height*step+i]=0;

            }

        }

    }

    for (int t=0;t<4;t++)

    {

        for (int i=0;i<ceil_width;i++)

        {

            for (int j=0;j<ceil_height;j++)

            {

                if (data_src[j*step+t*ceil_height*step+i+ceil_width]>thresol[t+4])

                {

                    data_dst[j*step+t*ceil_height*step+i+ceil_width]=255;

                }

                else

                    data_dst[j*step+t*ceil_height*step+i+ceil_width]=0;

            }

        }

    }

}

int CopencvDlg::Otsu(IplImage *src)

{

    int width=src->width;  

    int height=src->height;  

    int step=src->widthStep; 

    float histogram[256]={0};  

    unsigned char* p=(unsigned char*)src->imageData;  

    for(int i=0;i<height;i++) 

    {  

        for(int j=0;j<width;j++) 

        {  

            histogram[p[i*step+j]]++;  

        }  

    }  

    //normalize histogram  

    int size=height*width;  

    for(int i=0;i<256;i++) 

    {  

        histogram[i]=histogram[i]/size;  

    }  

    //average pixel value  

    float avgValue=0;  

    for(int i=0;i<256;i++) 

    {  

        avgValue+=i*histogram[i];  

    }  

    int threshold;      

    float sum0=0, sum1=0; //存储前景的灰度总和和背景灰度总和  

    float cnt0= 0, cnt1=0; //前景的总个数和背景的总个数  

    float w0=0, w1=0; //前景和背景所占整幅图像的比例  

    float u0=0, u1=0;  //前景和背景的平均灰度  

    float variance = 0; //最大类间方差  

    int i,j;  

    float u=0;  

    float maxVariance = 0;  

    for(i =1;i<256;i++) //一次遍历每个像素  

    {    

        sum0=0;  

        sum1=0;   

        cnt0=0;  

        cnt1=0;  

        w0=0;  

        w1=0;  

        for(j=0;j<i;j++)  

        {  

            cnt0+=histogram[j];  

            sum0+=j*histogram[j];  

        

        u0=sum0/cnt0;   

        //w0=cnt0/size; 

        w0=cnt0;

        for(j =i;j<=255;j++)  

        {  

            cnt1+=histogram[j];  

            sum1+=j*histogram[j];  

        

        u1=sum1/cnt1;  

        w1=cnt1;

        //w1=1-w0; // (double)cnt1 / size;  

        u=u0*w0+u1*w1; //图像的平均灰度 

        variance=float(w0*w1*(u0-u1)*(u0 - u1)); 

        if(variance > maxVariance)   //类间方差最大时为所求阈值

        {    

            maxVariance = variance;    

            threshold = i;    

        }

    }

    return threshold;

}

```

来自为知笔记(Wiz)

时间: 2024-08-30 14:57:44

最大类间方差法的相关文章

最大类间方差法(Otsu)

由Otsu(大津展之)于1978年提出的最大类间方差法,是引起较多关注的一种阈值选取方法.它是在判决分析或最小二乘原理的基础上推导出来的. 参考文献: [1] Otsu N. A threshold selection method from gray-level histogram. IEEE Trans,1979;SMC-9;62-66 下载地址 算法思想: 假设一幅图像有L个灰度级[1,2,…,L].灰度级为i的像素点的个数为ni,那么总的像素点个数就应该为N=n1+n2+…+nL.为了讨

iOS设计模式 - (2)UML类间关系精解

在正式讲设计模式之前, 介绍一下UML类图之间的关系还是非常有必要的, 由于一些教程, 书籍, 包含我之后的文章, 都会大量使用类图, 去描写叙述各个类之间的关系.这是一种非常直观, 简约的方式. 当然, 能力, 精力有限, 这里的UML的介绍也仅仅局限与几种常见的类间关系. 包含: 继承.实现.依赖.关联.聚合.组合 在次之前, 假设看不懂类图, 能够先看一下我之前写的一篇文章 : 具体解释八大UML类图符号的表示法 iOS - UML类间关系精解           by Colin丶 转载

iOS设计模式 - UML类间关系精解

在正式讲设计模式之前, 介绍一下UML类图之间的关系还是很有必要的, 因为一些教程, 书籍, 包括我之后的文章, 都会大量使用类图, 去描述各个类之间的关系.这是一种非常直观, 简约的方式. 当然, 能力, 精力有限, 这里的UML的介绍也仅仅局限与几种常见的类间关系. 包括: 继承.实现.依赖.关联.聚合.组合 在次之前, 如果看不懂类图, 可以先看一下我之前写的一篇文章 : 详解八大UML类图符号的表示法 iOS - UML类间关系精解           by Colin丶 转载请注明出处

类间的关系

类间关系可分为依赖.关联.聚合.组合和继承5种. 按照上述顺序,类间关系依次增强. 若类A的方法中仅仅使用了类B的对象,那么类A依赖于类B. 泛化/概化关系表示把几类对象类的公共属性和行为抽象成超类,然后其属性和方法被那些子类继承: 若类B除具有类A的全部特性外,类B还可定义新的特性以及置换类A的部分特性,则类B与类A具有泛化关系: 聚合关系表示一个较大的“整体”类包含一个或多个较小的“部分”类: 若类A的对象维持类B对象的引用或指针,并可与类C的对象共享相同的类B的对象,那么类A与类 B具有聚

里氏替换原则:切忌按照常识实现类间的继承关系

什么是里氏替换原则 里氏替换原则(Liskov Substitution Principle LSP)定义为:任何基类可以出现的地方,子类一定可以出现. LSP是继承复用的基石,只有当衍生类可以替换掉基类,软件单位的功能不受到影响时,基类才能真正被复用,而衍生类也能够在基类的基础上增加新的行为. 为什么需要里氏替换原则 里氏替换原则看起来好像没啥了不起的,不就是继承要注意的一丢丢细节么,年轻人呐,你这样的思想很危险啊.事实上里氏替换原则常常会被违反,我在下面举例说明吧: 我们定义了一个矩形类:

Flex事件机制学习-自定义事件实现类间通信 .

今天,学习Flex自定义事件,可以使两个类通信,定义一个Main类. public class Main extends Sprite     {            public function Main()            { //演示ChildSprite类是与Main类通信,ChildSprite类稍后说明: var child:ChildSprite=new ChildSprite(); //指示该实例的属性值            child.flag="01";

设计模式之UML类图以及类间关系

类图是描述系统中的类,以及各个类之间的关系的静态视图.能够让我们在正确编写代码以前对系统有一个全面的认识.类图是一种模型类型,确切的说,是一种静态模型类型.类图表示类.接口和它们之间的协作关系. 以下类图都是用 Visio 画的,因为这学期体系结构老师的实验报告强制使用这个软件画图. 类图的组成 普通类 一个类图由三部分组成. 第一部分是类名: 第二部分是属性,即成员变量.格式为:可见性 属性名称:类型[ = 缺省值]. 第三部分是操作,即方法.格式为:可见性 方法名称(参数列表)[ : 返回类

设计模式之UML(一)类图以及类间关系(泛化 、实现、依赖、关联、聚合、组合)

类图用于描述系统中所包含的类以及它们之间的相互关系,帮助人们简化对系统的理解,它是系统分析和设计阶段的重要产物,也是系统编码和测试的重要模型依据.接下来我们就来谈谈类图的组成,在下一篇中我们将讨论一下类图之间的关系. 一.类图的组成 1. 普通类 上图就是一个UML的普通类图,从上图我们看出,一个UML通常由三部分组成. 第一部分是类名:每个类都必须有一个名字,类名是一个字符串. 第二部分是类的属性(Attributes):属性是指类的性质,即类的成员变量.一个类可以有任意多个属性,也可以没有属

虎记:强大的nth-child(n)伪类选择器玩法

转载前端小哥:https://www.cnblogs.com/hu-w/p/5289668.html 写在前面的戏: 最近参加了度娘前端IFE的春季班,刷任务,百度真是有营销头脑,让咱们这帮未来的技术狂人为他到处打广告(我可不去哪),其中做的几个任务中有几个以前没有用到的东西, 也算是有些许收获(现在做了一半任务哦,萌萌哒),今天就来捋一捋css强大的nth-child(n)选择器功能(以庆祝博客粉丝突破YI员,访问量突破一百大关,可喜可贺,荣登博客名人指日可待!!) (常规选择器的YY) 这里