迭代法求图像的最佳阀值

在《图像的采样与量化及直方图》中讲述了如何计算图像的灰度直方图及对图像进行二值化处理,在这一文章中讲述的二值化处理的阀值都是自己设定的,自己设定的阀值往往不准确,而且不同的图像的最佳阀值是不一样的。那么能不能让计算机来计算图像的最佳阀值呢?答案是肯定的,下面就介绍一种迭代法计算图像阀值的方法:

算法思想

迭代法是基于逼近的思想,其步骤如下:

1.  求出图象的最大灰度值和最小灰度值,分别记为Pmax和Pmin,令初始阈值T0=(Pmax+Pmin)/2;

2.  根据阈值T(k)(k=0,1,2...,k)将图象分割为前景和背景,分别求出两者的平均灰度值H1和H2;

3.  求出新阈值T(k+1)=(H1+H2)/2;

4.  若T(k)=T(k+1),则所得即为阈值;否则转2,迭代计算。

源码(java)

/**
	 * 用迭代法 求最佳阀值
	 * @param pix 灰度像素数组
	 * @return 最佳阀值
	 */
	public int iterationGetThreshold(int[] pix) {
		int min = pix[0], max = pix[0];
		for(int i=0; i<pix.length; i++) {
			if(pix[i] > 255) {
				pix[i] = 255;
			}
			if(pix[i] < 0) {
				pix[i] = 0;
			}
			if(min >pix[i])
				min = pix[i];
			if(max <pix[i])
				max = pix[i];
		}
		double histo[] = getHisto(pix);
		int threshold = 0;
		int newThreshold = (int) ((min+max)/2);;
		while(threshold != newThreshold) {
			double sum1=0, sum2=0, w1=0, w2=0 ;
			int avg1, avg2;
			for(int i=min; i<newThreshold; i++) {
				sum1 += histo[i]*i;
				w1 += histo[i];
			}
			avg1 = (int) (sum1/w1);
			for(int i=newThreshold; i<max; i++) {
				sum2 += histo[i]*i;
				w2 += histo[i];
			}
			avg2 = (int) (sum2/w2);
			//System.out.println("avg1:" + avg1 + "  avg2:" + avg2 + "  newThreshold:" + newThreshold);
			threshold = newThreshold;
			newThreshold = (avg1+avg2)/2;
		}
		return newThreshold;
		
		/*if(min==0 && max == 255) {
			return (min+max)/2;
		} else {
			int t = (min+max)/2;
			double sum1=0, sum2=0, w1=0, w2=0 ;
			int avg1, avg2;
			for(int i=min; i<t; i++) {
				sum1 += histo[i]*i;
				w1 += histo[i];
			}
			avg1 = (int) (sum1/w1);
			for(int i=t; i<max; i++) {
				sum2 += histo[i]*i;
				w2 += histo[i];
			}
			avg2 = (int) (sum2/w2);
			return (avg1+avg2)/2;
		} */
	}
	/**
	 * 求图像的灰度直方图
	 * @param pix 一维的灰度图像像素值
	 * @return 0-255的 像素值所占的比率
	 */
	public double[] getHisto(int pix[]) {
		double histo[] = new double[256];
		for(int i=0; i<pix.length; i++) {
			//System.out.println("pix[i]:" + pix[i]);
			if(pix[i] > 255) {
				pix[i] = 255;
			}
			if(pix[i] < 0) {
				pix[i] = 0;
			}
			histo[pix[i]] ++;
		}
		for(int i=0; i<255; i++) {
			histo[i] = (double)histo[i]/pix.length;
		}
		return histo;
	}
	/**
	 * 求二值图像
	 * @param pix 像素矩阵数组
	 * @param w 矩阵的宽
	 * @param h 矩阵的高
	 * @param threshold 阀值
	 * @return 处理后的数组
	 */
	public int[] threshold(int pix[], int threshold) {
		for(int i=0; i<pix.length; i++) {
			if(pix[i] <= threshold) {
				pix[i] = 0;		
			} else {
				pix[i] = 255;
			}				
		}	
		return pix;
	}


评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

陌尘(MoChen)

爱打赏的人技术成长更开哦~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值