zoukankan      html  css  js  c++  java
  • 图像处理之常见二值化方法汇总

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

     

    图像二值化是图像分析与处理中最常见最重要的处理手段,二值处理方法也非常多。越

    精准的方法计算量也越大。本文主要介绍四种常见的二值处理方法,通常情况下可以满

    足大多数图像处理的需要。主要本文讨论的方法仅针对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步,

    直到计算出来的新阈值等于上一次阈值。

    前面三种在以前的博文中都有涉及,最后一种二值化方法的代码如下:

    [java] view plaincopy
     
     
    1. package com.gloomyfish.filter.study;  
    2.   
    3. import java.awt.image.BufferedImage;  
    4. import java.util.ArrayList;  
    5. import java.util.List;  
    6.   
    7. public class ThresholdBinaryFilter extends GrayFilter {  
    8.   
    9.     @Override  
    10.     public BufferedImage filter(BufferedImage src, BufferedImage dest) {  
    11.         int width = src.getWidth();  
    12.         int height = src.getHeight();  
    13.   
    14.         if ( dest == null )  
    15.             dest = createCompatibleDestImage( src, null );  
    16.   
    17.         int[] inPixels = new int[width*height];  
    18.         int[] outPixels = new int[width*height];  
    19.         src = super.filter(src, null); // we need to create new one  
    20.         getRGB( src, 0, 0, width, height, inPixels );  
    21.         int index = 0;  
    22.         int means = getThreshold(inPixels, height, width);  
    23.         for(int row=0; row<height; row++) {  
    24.             int ta = 0, tr = 0, tg = 0, tb = 0;  
    25.             for(int col=0; col<width; col++) {  
    26.                 index = row * width + col;  
    27.                 ta = (inPixels[index] >> 24) & 0xff;  
    28.                 tr = (inPixels[index] >> 16) & 0xff;  
    29.                 tg = (inPixels[index] >> 8) & 0xff;  
    30.                 tb = inPixels[index] & 0xff;  
    31.                 if(tr > means) {  
    32.                     tr = tg = tb = 255; //white  
    33.                 } else {  
    34.                     tr = tg = tb = 0; // black  
    35.                 }  
    36.                 outPixels[index] = (ta << 24) | (tr << 16) | (tg << 8) | tb;  
    37.             }  
    38.         }  
    39.         setRGB( dest, 0, 0, width, height, outPixels );  
    40.         return dest;  
    41.     }  
    42.   
    43.     private int getThreshold(int[] inPixels, int height, int width) {  
    44.         // maybe this value can reduce the calculation consume;   
    45.         int inithreshold = 127;  
    46.         int finalthreshold = 0;  
    47.         int temp[] = new int[inPixels.length];  
    48.         for(int index=0; index<inPixels.length; index++) {  
    49.             temp[index] = (inPixels[index] >> 16) & 0xff;  
    50.         }  
    51.         List<Integer> sub1 = new ArrayList<Integer>();  
    52.         List<Integer> sub2 = new ArrayList<Integer>();  
    53.         int means1 = 0, means2 = 0;  
    54.         while(finalthreshold != inithreshold) {  
    55.             finalthreshold = inithreshold;  
    56.             for(int i=0; i<temp.length; i++) {  
    57.                 if(temp[i] <= inithreshold) {  
    58.                     sub1.add(temp[i]);  
    59.                 } else {  
    60.                     sub2.add(temp[i]);  
    61.                 }  
    62.             }  
    63.             means1 = getMeans(sub1);  
    64.             means2 = getMeans(sub2);  
    65.             sub1.clear();  
    66.             sub2.clear();  
    67.             inithreshold = (means1 + means2) / 2;  
    68.         }  
    69.         long start = System.currentTimeMillis();  
    70.         System.out.println("Final threshold  = " + finalthreshold);  
    71.         long endTime = System.currentTimeMillis() - start;  
    72.         System.out.println("Time consumes : " + endTime);  
    73.         return finalthreshold;  
    74.     }  
    75.   
    76.     private static int getMeans(List<Integer> data) {  
    77.         int result = 0;  
    78.         int size = data.size();  
    79.         for(Integer i : data) {  
    80.             result += i;  
    81.         }  
    82.         return (result/size);  
    83.     }  
    84.   
    85. }  

    效果如下:

     
     
  • 相关阅读:
    【NOIP 2003】 加分二叉树
    【POJ 1655】 Balancing Act
    【HDU 3613】Best Reward
    【POJ 3461】 Oulipo
    【POJ 2752】 Seek the Name, Seek the Fame
    【POJ 1961】 Period
    【POJ 2406】 Power Strings
    BZOJ3028 食物(生成函数)
    BZOJ5372 PKUSC2018神仙的游戏(NTT)
    BZOJ4836 二元运算(分治FFT)
  • 原文地址:https://www.cnblogs.com/timssd/p/5830751.html
Copyright © 2011-2022 走看看