【Web】用遗传算法实现图像边缘提取

1.项目说明

这是自己写着玩的一个小项目,结合了遗传算法和图像分割的算法,实现了图像的边缘提取。图像分割的算法采用了大津阈值法,在该算法中,改造成使用遗传算法来寻找最佳阈值。该项目通过每隔1秒刷新界面的方式实时展示边缘提取的过程,并通过动态图表的方式展示每次遗传算法算出的最佳阈值。

2.效果展示

《【Web】用遗传算法实现图像边缘提取》

3.环境配置

  • 本项目采用HTML/CSS/JS编写,请使用chrome/firefox等主流浏览器查看。
  • 由于很多浏览器存在禁止跨域访问的问题,因此我把该项目部署到了服务器上。具体使用到的工具是tomcat。部署到服务器上后,直接点击starter.html即可运行。

4.算法知识介绍

  1. 大津阈值法
    最大类间方差法是由日本学者大津于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,即为所求。
  2. 遗传算法
    种群(Population):生物的进化以群体的形式进行,这样的一个群体称为种群。
    个体:组成种群的单个生物。
    基因 ( Gene ) :一个遗传因子。
    染色体 ( Chromosome ) :包含一组的基因。
    生存竞争,适者生存:对环境适应度高的、牛B的个体参与繁殖的机会比较多,后代就会越来越多。适应度低的个体参与繁殖的机会比较少,后代就会越来越少。
    遗传与变异:新个体会遗传父母双方各一部分的基因,同时有一定的概率发生基因变异。

    简单说来就是:繁殖过程,会发生基因交叉( Crossover )基因突变 ( Mutation ) ,适应度( Fitness )低的个体会被逐步淘汰,而适应度高的个体会越来越多。那么经过N代的自然选择后,保存下来的个体都是适应度很高的,其中很可能包含史上产生的适应度最高的那个个体。

    借鉴生物进化论,遗传算法将要解决的问题模拟成一个生物进化的过程,通过复制、交叉、突变等操作产生下一代的解,并逐步淘汰掉适应度函数值低的解,增加适应度函数值高的解。这样进化N代后就很有可能会进化出适应度函数值很高的个体。

5.代码实现

1.创建一个类,用来实现遗传算法的交叉,突变,产生下一代操作

var Genetic=function(src){
    this.count=1000;//迭代次数
    this.curchromo=new Array();//初始种群
    this.nextchromo=new Array();//更新后种群
    this.popnum=4;//初始化种群个数
    this.genenum=8;//基因位数
    this.myfun=myfun;
    this.crossrate=0.8;
    this.muterate=0.1;
    this.cmax=-1;
    this.canvas=document.getElementById("can");
    this.ctx=this.canvas.getContext('2d');
    //this.img=new Image();
    this.px;
    this.init=function(){
        var img=new Image();
        img.src='img/ss.jpg';
        ctx.drawImage(img,0,0,222,269);
        this.px=ctx.getImageData(0,0,222,269);
    }

    this.accute=function(){
        this.updatePop(this.curchromo,this.nextchromo);
        this.selection(this.nextchromo);
        this.crossover(this.nextchromo);
        this.mutation(this.nextchromo);
        this.updatePop(nextchromo,curchromo);
        this.cmax(curchromo);
    }
    this.cmax=function(curchromo){
       for (var i = 0; i <this.popnum; i++) {
          var maxval=(curchromo[i].fitValue>this.max)?curchromo[i].fitValue:this.max;
       }
    }
    //创建初始种群
    this.randCreatePop=function(curchromo){
        for(var i=0;i<this.popnum;i++){
            for(var j=0;j<this.genenum;j++){
                var randvalue=random();
                // this.curchromo[i]={
                // "geneBit":new Array(),
          // "fitValue":0
                // }
                var chromo=new Chromo();
                chromo.geneBit.length=0;//初始化
                chromo.geneBit.push(randvalue);

            }
            var value=this.binToDec(chromo);
            chromo.fitValue=this.calFitValue(value);//计算染色体的适应度值
            this.curchromo.push(chromo);//生成实验组

        }

    }
    //选择优良的个体
    this.selection=function(curchromo){
        for(var s=this.popnum;s>0;s--){
            for(var m=0;m<s-1;s++){
                if(curchromo[m+1].fitValue>curchromo[m].fitValue){
                    var tem=curchromo[m+1];
                    curchromo[m+1]=pop[m];
                    pop[m]=tem;
                }
            }
        }//排序
        var sumFitValue=0;
        for(var i=0;i<this.popnum;i++){
            sumFitValue+=curchromo[i].fitValue;
        }
        var avFitValue=sumFitValue/this.popnum;
        var choicePro=new Array(this.popnum);
        for(var j=0;j<this.popnum;j++){
           choicePro[j]=(curchromo[j].fitValue/sumFitValue)/(avFitValue/sumFitValue);
        }
        //根据选择概率来繁殖优良个体
        for(var t=0;t<this.popnum;t++){
            if((int)(choicePro[t]+0.55)==0)
                curchromo[this.popnum-1]=curchromo[0];
        }
    }
//交叉染色体的片段
    this.crossover=function(curchromo){
       if(Math.random()>this.crossrate){
              return;                     
       }
       for(var i=0;i<this.popnum;i+=2){
        var randPos=Math.round(Math.random()*(this.genenum-1));
        var s=i+1;
        for(var j=0;j<randPos;j++){
            var tmp=curchromo[i].geneBit[j];
            curchromo[i].geneBit[j]=curchromo[s].geneBit[j];
            curchromo[s].geneBit[j]=tmp;
        }
       }

       for(i=0;i<this.popnum;i++){
        curchromo[i].fitValue=this.calFitValue(binToDec(curchromo[i]));
       }
    }

//变异:随机改变染色体片段的值
    this.mutation=function(curchromo){
        var rndvalue=Math.round(Math.random()*100);
        if(rndvalue>=this.muterate*100){
            return;
        }
        var randgene=Math.round(Math.random()*(this.genenum-1));
        var randchromo=Math.round(Math.random()*(this.popnum-1));

        curchromo[randchromo].geneBit[randgene]=(curchromo[randchromo].geneBit[randgene]=='0')?'1':'0';
        curchromo[randchromo].fitValue=calFitValue(binToDec(curchromo[randchromo]));
    }

2.使用遗传算法计算最佳阈值

    this.calFitValue=function(target){

        var W0=0,W1=0,NUM0=0,NUM1=0,U0=0,U1=0,U,Gnow=0;
        var N0=0,N1=0; 
        for(var i=0;i<LENGTH;i+=4){
                    if(px.data[i]<=target){
                        N0+=1;
                        NUM0+=px.data[i];
                    }else{
                        N1+=1;
                        NUM1+=px.data[i];
                    }
                }
                W0=numberFormat(N0/(M*N),2);//前景像素点站整幅图的比例
                //W1=numberFormat(N1/(M*N),2);
                W1=numberFormat(1-W0,2);//后经像素点占整幅图的比例
                U0=(N0==0)?0:(NUM0/N0);//前景平均灰度
                U1=(N1==0)?0:(NUM1/N1);//后经平均灰度
                U=NUM0/(M*N)+NUM1/(M*N);//总平均灰度
                Gnow=W0*Math.pow((U0-U),2)+W1*Math.pow((U1-U),2);//g=ω0ω1(μ0-μ1)^2 //写入函数
                return Gnow;
    }

3.实时展示

function draw(){
    genetic.accute();
    var target=genetic.cmax;
    for(var i=0;i<px.data.length;i+=4){ if(px.data[i]<=target){ px.data[i]=0;px.data[i+1]=0;px.data[i+2]=0;px.data[i+3]=255; }else{ px.data[i]=255;px.data[i+1]=255;px.data[i+2]=255;px.data[i+3]=255; }
        }
    genetic.ctx.putImageData(px,0,0);       
}

6.源码下载

https://github.com/whuzxq/GA_engine

如果觉得帮助到你,就star一下吧~!

    原文作者:遗传算法
    原文地址: https://blog.csdn.net/WHUZXQ/article/details/62222873
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞