图像处理第二步:二值化

图像处理第二步:二值化

图像处理第二步:二值化

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

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步,


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

4)、OTSU算法

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


 
 
  1. int Threshold(int *hist) //compute the threshold
  2. {
  3. float u0, u1;
  4. float w0, w1;
  5. int count0;
  6. int t, maxT;
  7. float devi, maxDevi = 0; //方差及最大方差
  8. int i;
  9. int sum = 0;
  10. for (i = 0; i < 256; i++)
  11. {
  12. sum = sum + hist[i];
  13. }
  14. for (t = 0; t < 255; t++)
  15. {
  16. u0 = 0; count0 = 0;
  17. //阈值为t时,c0组的均值及产生的概率
  18. for (i = 0; i <= t; i++)
  19. {
  20. u0 += i * hist[i]; count0 += hist[i];
  21. }
  22. u0 = u0 / count0; w0 = ( float)count0/sum;
  23. //阈值为t时,c1组的均值及产生的概率
  24. u1 = 0;
  25. for (i = t + 1; i < 256; i++)
  26. {
  27. u1 += i * hist[i];
  28. }
  29. u1 = u1 / (sum - count0); w1 = 1 - w0;
  30. //两类间方差
  31. devi = w0 * w1 * (u1 - u0) * (u1 - u0);
  32. //记录最大的方差及最佳位置
  33. if (devi > maxDevi)
  34. {
  35. maxDevi = devi;
  36. maxT = t;
  37. }
  38. }
  39. return maxT;
  40. }
  41. //二值化处理
  42. void OTSU(IplImage *src, IplImage *dst)
  43. {
  44. int i = 0, j = 0;
  45. int wide = src->widthStep;
  46. int high = src->height;
  47. int hist[ 256] = { 0};
  48. int t;
  49. unsigned char *p, *q;
  50. for (j = 0; j < high; j ++)
  51. {
  52. p = ( unsigned char *)(src->imageData + j * wide);
  53. for (i = 0; i < wide; i++)
  54. {
  55. hist[p[i]]++; //统计直方图
  56. }
  57. }
  58. t = Threshold(hist);
  59. for (j = 0; j < high; j ++)
  60. {
  61. q = ( unsigned char *)(dst->imageData + j * wide);
  62. p = ( unsigned char *)(src->imageData + j * wide);
  63. for (i = 0; i < wide; i++)
  64. {
  65. q[i] = p[i] >= t ? 255 : 0;
  66. }
  67. }
  68. }
5)、Kittle算法

一种快速的全局阈值法。它的效果不比OTSU差多少,但速度快好多倍,如果可以应用在图像质量不错的环境。 它的中心思想是,计算整幅图像的梯度灰度的平均值,以此平均值做为阈值。

  
  
  1. //kittler算法
  2. for (i= 1;i<high -1;i++)
  3. {
  4. plineadd=src->imageData+i*wide;
  5. pNextLine=src->imageData+(i+ 1)*wide;
  6. pPreLine=src->imageData+(i -1)*wide;
  7. for(j= 1;j<wide -1;j++)
  8. {
  9. //求水平或垂直方向的最大梯度
  10. Grads=MAX( abs((uchar)pPreLine[j]-(uchar)pNextLine[j]), abs((uchar)plineadd[j -1]-(uchar)plineadd[j+ 1])); //max(xGrads,yGrads)
  11. sumGrads += Grads;
  12. //梯度与当前点灰度的积
  13. sumGrayGrads += Grads*((uchar)plineadd[j]);
  14. }
  15. }
  16. threshold=sumGrayGrads/sumGrads;
  17. // printf("%d\n",threshold);
  18. for(i= 0;i<high;i++)
  19. {
  20. plineadd=src->imageData+i*wide;
  21. pTempLine=kittler->imageData+i*wide;
  22. for(j= 0;j<wide;j++)
  23. {
  24. pTempLine[j]=(uchar)plineadd[j]>threshold? 255: 0;[ 3]
  25. }
  26. }





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值