图像处理------常见二值化方法汇总
2019-07-13 12:17发布
生成海报
图像二值化是图像分析与处理中最常见最重要的处理手段,二值处理方法也非常多。越精准的方法计算量也越大。本文主要介绍四种常见的二值处理方法,通常情况下可以满足大多数图像处理的需要。主要本文讨论的方法仅针对RGB {MOD}彩空间。 方法一:该方法非常简单,对RGB彩 {MOD}图像灰度化以后,扫描图像的每个像素值,值小于127的将像素值设为0(黑 {MOD}),值大于等于127的像素值设为255(白 {MOD})。该方法的好处是计算量少速度快。缺点更多首先阈值为127没有任何理由可以解释,其次完全不考虑图像的像素分布情况与像素值特征。可以说该方法是史最弱智的二值处理方法一点也不为过。 方法二:最常见的二值处理方法是计算像素的平均值K,扫描图像的每个像素值如像素值大于K像素值设为255(白 {MOD}),值小于等于K像素值设为0(黑 {MOD})。该方法相比方法一,阈值的选取稍微有点智商,可以解释。但是使用平均值作为二值化阈值同样有个致命的缺点,可能导致部分对象像素或者背景像素丢失。二值化结果不能真实反映源图像信息。 方法三:使用直方图方法来寻找二值化阈值,直方图是图像的重要特质,直方图方法选择二值化阈值主要是发现图像的两个最高的峰,然后在阈值取值在两个峰之间的峰谷最低处。该方法相对前面两种方法而言稍微精准一点点。结果也更让人可以接受。 方法四:http://en.wikipedia.org/wiki/Thresholding_(image_processing)使用近似一维Means方法寻找二值化阈值,该方法的大致步骤如下:1. 一个初始化阈值T,可以自己设置或者根据随机方法生成。2. 根据阈值图每个像素数据P(n,m)分为对象像素数据G1与背景像素数据G2。(n为行,m为列)3. G1的平均值是m1, G2的平均值是m24. 一个新的阈值T’ = (m1 + m2)/25. 回到第二步,用新的阈值继续分像素数据为对象与北京像素数据,继续2~4步,直到计算出来的新阈值等于上一次阈值。前面三种在以前的博文中都有涉及,最后一种二值化方法的代码如下:[java] view plaincopy- 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);
- getRGB( src, 0, 0, width, height, inPixels );
- int index = 0;
- int means = getThreshold(inPixels, height, width);
- for(int row=0; row
- int ta = 0, tr = 0, tg = 0, tb = 0;
- for(int col=0; 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;
- }
-
- private int getThreshold(int[] inPixels, int height, int width) {
-
- int inithreshold = 127;
- int finalthreshold = 0;
- int temp[] = new int[inPixels.length];
- for(int index=0; index
- temp[index] = (inPixels[index] >> 16) & 0xff;
- }
- List sub1 = new ArrayList();
- List sub2 = new ArrayList();
- int means1 = 0, means2 = 0;
- while(finalthreshold != inithreshold) {
- finalthreshold = inithreshold;
- for(int i=0; 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 data) {
- int result = 0;
- int size = data.size();
- for(Integer i : data) {
- result += i;
- }
- return (result/size);
- }
-
- }
效果如下:
打开微信“扫一扫”,打开网页后点击屏幕右上角分享按钮