安卓:自适应阈值处理

6

我正在尝试使用Android实现Derek Bradley的自适应阈值算法。但是它一直返回黑色像素。这是我的代码片段,请建议我该怎么做。提前致谢。

public static Bitmap GrayscaleToBin(Bitmap bm2)
{

    Bitmap bm;
    bm=bm2.copy(Config.ARGB_8888, true);
    final   int width = bm.getWidth();
    final  int height = bm.getHeight();
    int[]  pixels;
    pixels = new int[width*height];
    bm.getPixels(pixels,0,width,0,0,width,height);     
    //Bradley AdaptiveThrsholdging       
    int []intImg= new int[width*height];
    int sum=0;
    for(int i=0;i<width;++i){
        sum=0;
        for(int j=0;j<height;++j)
        {
            sum=sum+pixels[i+j*width];
            if(i==0){intImg[i+j*width]=sum;}
            else
            {
                intImg[i+j*width]= intImg[i-1+j*width]+sum;
            }
        }
    }
    int x1,x2,y1,y2=0,count=0;
    int s=width >> 3;   
    int t=15;
    for(int i=0;i<width;++i)
    {
        for(int j=0;j<height;++j)
        {
            x1=i-s/2;
            x2=i+s/2;
            y1=j-s/2;
            y2=j+s/2;
            if (x1 <0) x1 = 0;  
            if (x2>= width) x2 = width-1;  
            if (y1 <0) y1 = 0;  
            if (y2>= height) y2 = height-1;  
            count = (x2-x1) * (y2-y1);  
            sum = intImg [y2 * width + x2] -  
            intImg [y1 * width + x2] -  
            intImg [y2 * width + x1] +  
            intImg [y1 * width + x1]; 
            if((pixels[i+j*width]*count)<=(sum*(100-t)/100))
            {
                pixels[i+j*width]=0;
            }
            else
            {
                pixels[i+j*width]=255; 
            }
        }
    }
    /*---------------------------------------------------------------------------*/
    bm.setPixels(pixels,0,width,0,0,width,height);
    // Log.d("cdsfss","afterloop");
    return bm;
}

那篇论文涉及二值化,所以我对你的代码的第一个问题是函数名称“RGBtoGrayScale”。这立即引起了另一个问题,论文不关心RGB图像,但你的代码似乎没有确保输入是灰度图像。最后,你正在使用一种查找s x s平均值的公式,该公式与论文(或任何处理积分图像的文本)中的公式不同。你检查过这些问题吗? - mmgp
抱歉,函数名称未正确书写。我已更改它。我的输入位图图像是灰度图像,并且是在使用 R = G = B = (int)(0.299 * R + 0.587 * G + 0.114 * B) 进行 RGB 转换后获得的。但是,它与 s=width/8 不兼容。 - Moyeen
2个回答

10

经过长时间的努力,我使用以下代码解决了这个问题。

public static Bitmap GrayscaleToBin(Bitmap bm2)
 {
 Bitmap bm;
 bm=bm2.copy(Config.RGB_565, true);
 final   int width = bm.getWidth();
 final  int height = bm.getHeight();

 int pixel1,pixel2,pixel3,pixel4,A,R;
 int[]  pixels;
 pixels = new int[width*height];
 bm.getPixels(pixels,0,width,0,0,width,height);
 int size=width*height;
      int s=width/8;
      int s2=s>>1;
      double t=0.15;
      double it=1.0-t;
      int []integral= new int[size];
      int []threshold=new int[size];
      int i,j,diff,x1,y1,x2,y2,ind1,ind2,ind3;
      int sum=0;
      int ind=0;
      while(ind<size)
      {
       sum+=pixels[ind] & 0xFF;
       integral[ind]=sum;
       ind+=width;
      }
   x1=0;
   for(i=1;i<width;++i)       
   {
       sum=0;
       ind=i;
       ind3=ind-s2;
       if(i>s)
       {
           x1=i-s;
       }
       diff=i-x1;
       for(j=0;j<height;++j)
       {
           sum+=pixels[ind] & 0xFF;
           integral[ind]=integral[(int)(ind-1)]+sum;
           ind+=width;
           if(i<s2)continue;
           if(j<s2)continue;
           y1=(j<s ? 0 : j-s);
           ind1=y1*width;
           ind2=j*width;

        if (((pixels[ind3]&0xFF)*(diff * (j - y1))) < ((integral[(int)(ind2 + i)] - integral[(int)(ind1 + i)] - integral[(int)(ind2 + x1)] + integral[(int)(ind1 + x1)])*it)) {
            threshold[ind3] = 0x00;
        } else {
            threshold[ind3] = 0xFFFFFF;
        }
        ind3 += width;
    }
}

y1 = 0;
for( j = 0; j < height; ++j )
{
    i = 0;
    y2 =height- 1;
    if( j <height- s2 ) 
    {
        i = width - s2;
        y2 = j + s2;
    }

    ind = j * width + i;
    if( j > s2 ) y1 = j - s2;
    ind1 = y1 * width;
    ind2 = y2 * width;
    diff = y2 - y1;
    for( ; i < width; ++i, ++ind )
    {

        x1 = ( i < s2 ? 0 : i - s2);
        x2 = i + s2;

        // check the border
        if (x2 >= width) x2 = width - 1;

        if (((pixels[ind]&0xFF)*((x2 - x1) * diff)) < ((integral[(int)(ind2 + x2)] - integral[(int)(ind1 + x2)] - integral[(int)(ind2 + x1)] + integral[(int)(ind1 + x1)])*it)) {
            threshold[ind] = 0x00;
        } else {
            threshold[ind] = 0xFFFFFF;
        }
    }
}
   /*-------------------------------
    * --------------------------------------------*/
   bm.setPixels(threshold,0,width,0,0,width,height);

   return bm;
}

那么问题出在哪里呢?我几乎有与问题中发布的代码完全相同的代码,并且得到类似的输出(完全是黑色或白色),但是这段代码对我来说是不可读的,所以我不知道现在有什么不同。 - Gooey
区别在于,第一个示例使用了ARGB_8888,而这个示例使用的是RGB_565。 - Maxim M

4
你可以使用Catalano Framework。在samples文件夹中有一个使用Bradley用于Android的示例。
FastBitmap fb = new FastBitmap(bitmap);

fb.toGrayscale();

BradleyLocalThreshold bradley = new BradleyLocalThreshold();
bradley.applyInPlace(fb);

bitmap = fb.toBitmap();

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接