图像处理之特殊灰度算法技巧

 - created by gloomyfish

图像处理之特殊灰度算法技巧


介绍几种特殊的灰度算法滤镜,将彩色图像转换为灰度图像。其中涉及到的有基于阈值的图

像二值化,弗洛伊德.斯坦德伯格抖动算法,基于阈值的部分灰度化

 

基础知识怎么把RGB转换为单色的[0 ~256]之间的灰度,最常用的转换公式如下:

Gray = 0.299 * red + 0.587 * green + 0.114 * blue;

 

1.       基于像素平均值的图像阈值二值化算法:

处理流程:

a.      首先将彩色图像转换为灰度图像

b.      计算灰度图像的算术平均值– M

c.      以M为阈值,完成对灰度图二值化( 大于阈值M,像素点赋值为白色,否则赋值为黑

色)

图像效果:


关键代码:

public BufferedImage filter(BufferedImage src, BufferedImage dest) {  
    int width = src.getWidth();  
       int height = src.getHeight();  
  
       if ( dest == null )  
           dest = createCompatibleDestImage( src, null );  
       src = super.filter(src, dest);  
  
       int[] inPixels = new int[width*height];  
       int[] outPixels = new int[width*height];  
       getRGB(src, 0, 0, width, height, inPixels );  
         
       // calculate means of pixel    
       int index = 0;    
       double redSum = 0, greenSum = 0, blueSum = 0;    
       double total = 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;    
               redSum += tr;    
               greenSum += tg;    
               blueSum +=tb;    
           }    
       }  
       int means = (int)(redSum / total);  
       System.out.println(" threshold average value = " + means);  
         
       // dithering   
       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;  
               } else {  
                tr = tg = tb = 0;  
               }  
               outPixels[index] = (ta << 24) | (tr << 16) | (tg << 8) | tb;  
                 
        }  
       }  
       setRGB( dest, 0, 0, width, height, outPixels );  
       return dest;  
}  

2.       基于错误扩散的Floyd-Steinberg抖动算法

关于什么是Floyd-Steinberg抖动,参见这里

http://en.wikipedia.org/wiki/Floyd–Steinberg_dithering

图像效果:

关键代码:

@Override  
public BufferedImage filter(BufferedImage src, BufferedImage dest) {  
    int width = src.getWidth();  
       int height = src.getHeight();  
  
       if ( dest == null )  
        dest = createCompatibleDestImage( src, null );  
       src = super.filter(src, dest);  
  
       int[] inPixels = new int[width*height];  
       int[] outPixels = new int[width*height];  
       getRGB( src, 0, 0, width, height, inPixels );  
       int index = 0;  
       for(int row=0; row<height; row++) {  
        for(int col=0; col<width; col++) {  
            index = row * width + col;  
               int r1 = (inPixels[index] >> 16) & 0xff;  
               int g1 = (inPixels[index] >> 8) & 0xff;  
               int b1 = inPixels[index] & 0xff;  
               int cIndex = getCloseColor(r1, g1, b1);  
               outPixels[index] = (255 << 24) | (COLOR_PALETTE[cIndex][0] << 16) | (COLOR_PALETTE[cIndex][1] << 8) | COLOR_PALETTE[cIndex][2];  
               int er = r1 - COLOR_PALETTE[cIndex][0];  
               int eg = g1 - COLOR_PALETTE[cIndex][1];  
               int eb = b1 -  COLOR_PALETTE[cIndex][2];  
               int k = 0;  
                 
               if(row + 1 < height && col - 1 > 0) {  
                k = (row + 1) * width + col - 1;  
                   r1 = (inPixels[k] >> 16) & 0xff;  
                   g1 = (inPixels[k] >> 8) & 0xff;  
                   b1 = inPixels[k] & 0xff;  
                   r1 += (int)(er * kernelData[0]);  
                   g1 += (int)(eg * kernelData[0]);  
                   b1 += (int)(eb * kernelData[0]);  
                   inPixels[k] = (255 << 24) | (clamp(r1) << 16) | (clamp(g1) << 8) | clamp(b1);  
               }  
                 
               if(col + 1 < width) {  
                k = row * width + col + 1;  
                   r1 = (inPixels[k] >> 16) & 0xff;  
                   g1 = (inPixels[k] >> 8) & 0xff;  
                   b1 = inPixels[k] & 0xff;  
                   r1 += (int)(er * kernelData[3]);  
                   g1 += (int)(eg * kernelData[3]);  
                   b1 += (int)(eb * kernelData[3]);  
                   inPixels[k] = (255 << 24) | (clamp(r1) << 16) | (clamp(g1) << 8) | clamp(b1);  
               }  
                 
               if(row + 1 < height) {  
                k = (row + 1) * width + col;  
                   r1 = (inPixels[k] >> 16) & 0xff;  
                   g1 = (inPixels[k] >> 8) & 0xff;  
                   b1 = inPixels[k] & 0xff;  
                   r1 += (int)(er * kernelData[1]);  
                   g1 += (int)(eg * kernelData[1]);  
                   b1 += (int)(eb * kernelData[1]);  
                   inPixels[k] = (255 << 24) | (clamp(r1) << 16) | (clamp(g1) << 8) | clamp(b1);  
               }  
                 
               if(row + 1 < height && col + 1 < width) {  
                k = (row + 1) * width + col + 1;  
                   r1 = (inPixels[k] >> 16) & 0xff;  
                   g1 = (inPixels[k] >> 8) & 0xff;  
                   b1 = inPixels[k] & 0xff;  
                   r1 += (int)(er * kernelData[2]);  
                   g1 += (int)(eg * kernelData[2]);  
                   b1 += (int)(eb * kernelData[2]);  
                   inPixels[k] = (255 << 24) | (clamp(r1) << 16) | (clamp(g1) << 8) | clamp(b1);  
               }  
        }  
       }  
       setRGB( dest, 0, 0, width, height, outPixels );  
       return dest;  
}  

3.       选择性灰度算法

计算选择的颜色与像素灰度颜色之间的几何距离值,跟阈值比较决定是否像素点为灰度

值,可以得到一些让你意想不到的图像处理效果!

图像效果 (Main Color = GREEN, 阈值 = 200)

原图:


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];  
       getRGB( src, 0, 0, width, height, inPixels );  
       int index = 0;  
       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;  
               int gray = (int)(0.299 * (double)tr + 0.587 * (double)tg + 0.114 * (double)tb);  
               double distance = getDistance(tr, tg, tb);  
               if(distance < threshold) {  
                double k = distance / threshold;  
                int[] rgb = getAdjustableRGB(tr, tg, tb, gray, (float)k);  
                tr = rgb[0];  
                tg = rgb[1];  
                tb = rgb[2];  
                outPixels[index] = (ta << 24) | (tr << 16) | (tg << 8) | tb;  
               } else {  
                outPixels[index] = (ta << 24) | (gray << 16) | (gray << 8) | gray;                      
               }  
                 
        }  
       }  
       setRGB( dest, 0, 0, width, height, outPixels );  
       return dest;  
}  

创建新的目标Image  

public BufferedImage createCompatibleDestImage(BufferedImage src, ColorModel dstCM) {  
    if ( dstCM == null )  
        dstCM = src.getColorModel();  
    return new BufferedImage(dstCM, dstCM.createCompatibleWritableRaster(src.getWidth(), src.getHeight()), dstCM.isAlphaPremultiplied(), null);  
}  


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值