图像处理第二步:二值化

图像处理第二步:二值化

第一种分类:(局部与整体)

1、全局二值化

设定一个全局的阈值T,用T将图像的数据分成两部分:大于T的像素群和小于T的像素群。将大于T的像素群的像素值设定为白色(或者黑色),小于T的像素群的像素值设定为黑色(或者白色)。

2、局部自适应二值化

局部二值化的方法就是按照一定的规则将整幅图像划分为N个窗口,对这N个窗口中的每一个窗口再按照一个统一的阈值T将该窗口内的像素划分为两部分,进行二值化处理。

第二种分类:(按照阈值选取方法不同来分类)

1、固定阈值

直接设定一个阈值,阈值的选取或者根据所处理问题的实际情况,或者毫不讲理心血来潮随便设定一个中间值,这种算法意义不大。

2、自适应阈值

1)、以图像的平均灰度值作为阈值。

使用平均值作为二值化阈值同样有个致命的缺点,可能导致部分对象像素或者背景像素丢失。二值化结果不能真实反映源图像信息。

2)、使用直方图方法来寻找二值化阈值。

直方图方法选择二值化阈值主要是发现图像的两个最高的峰,然后在阈值取值在两个峰之间的峰谷最低处。该方法相对前面两种方法而言稍微精准一点点。结果也更让人可以接受。

3)、使用近似一维Means方法寻找二值化阈值

该方法的大致步骤如下:

1.      一个初始化阈值T,可以自己设置或者根据随机方法生成。

2.      根据阈值图每个像素数据P(n,m)分为对象像素数据G1与背景像素数据G2。(n为行,m为列)

3.      G1的平均值是m1, G2的平均值是m2

4.      一个新的阈值T’ = (m1 + m2)/2

5.      回到第二步,用新的阈值继续分像素数据为对象与北京像素数据,继续2~4步,

package com.gloomyfish.filter.study;  
  
import java.awt.image.BufferedImage;  
import java.util.ArrayList;  
import java.util.List;  
  
public class ThresholdBinaryFilter extends GrayFilter {  
  
    @Override  
    public BufferedImage filter(BufferedImage src, BufferedImage dest) {  
        int width = src.getWidth();  
        int height = src.getHeight();  
  
        if ( dest == null )  
            dest = createCompatibleDestImage( src, null );  
  
        int[] inPixels = new int[width*height];  
        int[] outPixels = new int[width*height];  
        src = super.filter(src, null); // we need to create new one  
        getRGB( src, 0, 0, width, height, inPixels );  
        int index = 0;  
        int means = getThreshold(inPixels, height, width);  
        for(int row=0; row<height; row++) {  
            int ta = 0, tr = 0, tg = 0, tb = 0;  
            for(int col=0; col<width; col++) {  
                index = row * width + col;  
                ta = (inPixels[index] >> 24) & 0xff;  
                tr = (inPixels[index] >> 16) & 0xff;  
                tg = (inPixels[index] >> 8) & 0xff;  
                tb = inPixels[index] & 0xff;  
                if(tr > means) {  
                    tr = tg = tb = 255; //white  
                } else {  
                    tr = tg = tb = 0; // black  
                }  
                outPixels[index] = (ta << 24) | (tr << 16) | (tg << 8) | tb;  
            }  
        }  
        setRGB( dest, 0, 0, width, height, outPixels );  
        return dest;  
    }  
  
    private int getThreshold(int[] inPixels, int height, int width) {  
        // maybe this value can reduce the calculation consume;   
        int inithreshold = 127;  
        int finalthreshold = 0;  
        int temp[] = new int[inPixels.length];  
        for(int index=0; index<inPixels.length; index++) {  
            temp[index] = (inPixels[index] >> 16) & 0xff;  
        }  
        List<Integer> sub1 = new ArrayList<Integer>();  
        List<Integer> sub2 = new ArrayList<Integer>();  
        int means1 = 0, means2 = 0;  
        while(finalthreshold != inithreshold) {  
            finalthreshold = inithreshold;  
            for(int i=0; i<temp.length; i++) {  
                if(temp[i] <= inithreshold) {  
                    sub1.add(temp[i]);  
                } else {  
                    sub2.add(temp[i]);  
                }  
            }  
            means1 = getMeans(sub1);  
            means2 = getMeans(sub2);  
            sub1.clear();  
            sub2.clear();  
            inithreshold = (means1 + means2) / 2;  
        }  
        long start = System.currentTimeMillis();  
        System.out.println("Final threshold  = " + finalthreshold);  
        long endTime = System.currentTimeMillis() - start;  
        System.out.println("Time consumes : " + endTime);  
        return finalthreshold;  
    }  
  
    private static int getMeans(List<Integer> data) {  
        int result = 0;  
        int size = data.size();  
        for(Integer i : data) {  
            result += i;  
        }  
        return (result/size);  
    }  
  
}  

4)、OTSU算法

OTSU的中心思想是阈值T应使目标与背景两类的类间方差最大。

int Threshold(int *hist) //compute the threshold
{
float u0, u1;
float w0, w1;
int count0;
int t, maxT;
float devi, maxDevi = 0; //方差及最大方差
int i;
int sum = 0;
for (i = 0; i < 256; i++)
{
sum = sum + hist[i];
}
for (t = 0; t < 255; t++)
{
u0 = 0; count0 = 0;
//阈值为t时,c0组的均值及产生的概率
for (i = 0; i <= t; i++)
{
u0 += i * hist[i]; count0 += hist[i];
}
u0 = u0 / count0; w0 = (float)count0/sum;
//阈值为t时,c1组的均值及产生的概率
u1 = 0;
for (i = t + 1; i < 256; i++)
{
u1 += i * hist[i];
}
u1 = u1 / (sum - count0); w1 = 1 - w0;
//两类间方差
devi = w0 * w1 * (u1 - u0) * (u1 - u0);
//记录最大的方差及最佳位置
if (devi > maxDevi)
{
maxDevi = devi;
maxT = t;
}
}
return maxT;
}
//二值化处理
void OTSU(IplImage *src, IplImage *dst)
{
int i = 0, j = 0;
int wide = src->widthStep;
int high = src->height;
int hist[256] = {0};
int t;
unsigned char *p, *q;
for (j = 0; j < high; j ++)
{
p = (unsigned char *)(src->imageData + j * wide);
for (i = 0; i < wide; i++)
{
hist[p[i]]++; //统计直方图
}
}
t = Threshold(hist);
for (j = 0; j < high; j ++)
{
q = (unsigned char *)(dst->imageData + j * wide);
p = (unsigned char *)(src->imageData + j * wide);
for (i = 0; i < wide; i++)
{
q[i] = p[i] >= t ? 255 : 0;
}
}
}
5)、Kittle算法

一种快速的全局阈值法。它的效果不比OTSU差多少,但速度快好多倍,如果可以应用在图像质量不错的环境。 它的中心思想是,计算整幅图像的梯度灰度的平均值,以此平均值做为阈值。
//kittler算法
for (i=1;i<high-1;i++)
{
plineadd=src->imageData+i*wide;
pNextLine=src->imageData+(i+1)*wide;
pPreLine=src->imageData+(i-1)*wide;
for(j=1;j<wide-1;j++)
{
//求水平或垂直方向的最大梯度
Grads=MAX(abs((uchar)pPreLine[j]-(uchar)pNextLine[j]),abs((uchar)plineadd[j-1]-(uchar)plineadd[j+1])); //max(xGrads,yGrads)
sumGrads += Grads;
//梯度与当前点灰度的积
sumGrayGrads += Grads*((uchar)plineadd[j]);
}
}
threshold=sumGrayGrads/sumGrads;
// printf("%d\n",threshold);
for(i=0;i<high;i++)
{
plineadd=src->imageData+i*wide;
pTempLine=kittler->imageData+i*wide;
for(j=0;j<wide;j++)
{
pTempLine[j]=(uchar)plineadd[j]>threshold?255:0;[3]
}
}





  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值