图像处理第二步:二值化
来源:互联网 发布:java线程创建方式 编辑:程序博客网 时间:2024/05/27 09:48
图像处理第二步:二值化
第一种分类:(局部与整体)
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步,
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); } }
4)、OTSU算法
OTSU的中心思想是阈值T应使目标与背景两类的类间方差最大。
int Threshold(int *hist) //compute the threshold{float u0, u1;float w0, w1;int count0;int t, maxT;float devi, maxDevi = 0; //方差及最大方差int i;int sum = 0;for (i = 0; i < 256; i++){sum = sum + hist[i];}for (t = 0; t < 255; t++){u0 = 0; count0 = 0;//阈值为t时,c0组的均值及产生的概率for (i = 0; i <= t; i++){u0 += i * hist[i]; count0 += hist[i];}u0 = u0 / count0; w0 = (float)count0/sum;//阈值为t时,c1组的均值及产生的概率u1 = 0;for (i = t + 1; i < 256; i++){u1 += i * hist[i];}u1 = u1 / (sum - count0); w1 = 1 - w0;//两类间方差devi = w0 * w1 * (u1 - u0) * (u1 - u0);//记录最大的方差及最佳位置if (devi > maxDevi){maxDevi = devi;maxT = t;}}return maxT;}//二值化处理void OTSU(IplImage *src, IplImage *dst){int i = 0, j = 0;int wide = src->widthStep;int high = src->height;int hist[256] = {0};int t;unsigned char *p, *q;for (j = 0; j < high; j ++){p = (unsigned char *)(src->imageData + j * wide);for (i = 0; i < wide; i++){hist[p[i]]++; //统计直方图}}t = Threshold(hist);for (j = 0; j < high; j ++){q = (unsigned char *)(dst->imageData + j * wide);p = (unsigned char *)(src->imageData + j * wide);for (i = 0; i < wide; i++){q[i] = p[i] >= t ? 255 : 0;}}}5)、Kittle算法
//kittler算法for (i=1;i<high-1;i++){plineadd=src->imageData+i*wide;pNextLine=src->imageData+(i+1)*wide;pPreLine=src->imageData+(i-1)*wide;for(j=1;j<wide-1;j++){//求水平或垂直方向的最大梯度Grads=MAX(abs((uchar)pPreLine[j]-(uchar)pNextLine[j]),abs((uchar)plineadd[j-1]-(uchar)plineadd[j+1])); //max(xGrads,yGrads)sumGrads += Grads;//梯度与当前点灰度的积sumGrayGrads += Grads*((uchar)plineadd[j]);}}threshold=sumGrayGrads/sumGrads;// printf("%d\n",threshold);for(i=0;i<high;i++){plineadd=src->imageData+i*wide;pTempLine=kittler->imageData+i*wide;for(j=0;j<wide;j++){pTempLine[j]=(uchar)plineadd[j]>threshold?255:0;[3]}}
- 图像处理第二步:二值化
- HTML5/JavaScript 图像边缘羽化— 打造图像处理类库第二步
- 图像处理算法系列 第二章 二值化
- 第二章图像处理
- MATLAB图像处理第二节
- 图像处理——第二篇 Java图形图像处理
- 图像处理之二值化图像
- Linux 第二步
- 第二步 对象
- 万里长征第二步
- Starling第二步
- Linux 第二步
- 读《程序员第二步》
- Jquery第二步
- 学习View第二步
- 海思Hi3518e第二步
- diango项目第二步
- 毕设第二步
- iOS7 设置指定某行的的分隔线不显示
- 图像处理第一步:灰度化
- 信息系统项目管理师总结1
- Eclipse NDK 配置,不用安装Cygwin
- 自定义Notification
- 图像处理第二步:二值化
- 基于qt和mysql的学生注册系统(二)
- java速度入门一
- VS2012,更新补丁后的残忍--创建项目未找到与约束匹配的导出
- 如何方便输入德语、法语、俄语特殊字符
- java速度入门二
- java速度入门三
- 查询的意图识别
- JVM client模式和Server模式的区别