您的位置:首页 > 其它

图像处理之常见二值化方法汇总

2012-10-15 20:41 471 查看
图像处理之常见二值化方法汇总
图像二值化是图像分析与处理中最常见最重要的处理手段,二值处理方法也非常多。越
精准的方法计算量也越大。本文主要介绍四种常见的二值处理方法,通常情况下可以满
足大多数图像处理的需要。主要本文讨论的方法仅针对RGB色彩空间。

方法一:
该方法非常简单,对RGB彩色图像灰度化以后,扫描图像的每个像素值,值小于127的
将像素值设为0(黑色),值大于等于127的像素值设为255(白色)。该方法的好处是计算
量少速度快。缺点更多首先阈值为127没有任何理由可以解释,其次完全不考虑图像的
像素分布情况与像素值特征。可以说该方法是史最弱智的二值处理方法一点也不为过。

方法二:
最常见的二值处理方法是计算像素的平均值K,扫描图像的每个像素值如像素值大于K
像素值设为255(白色),值小于等于K像素值设为0(黑色)。该方法相比方法一,阈值的
选取稍微有点智商,可以解释。但是使用平均值作为二值化阈值同样有个致命的缺点,
可能导致部分对象像素或者背景像素丢失。二值化结果不能真实反映源图像信息。

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

方法四:http://en.wikipedia.org/wiki/Thresholding_(image_processing)
使用近似一维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); 	}  }

效果如下:



本文出自 “流浪的鱼” 博客,请务必保留此出处http://gloomyfish.blog.51cto.com/8837804/1400328
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: