图像处理之积分图应用四(基于局部均值的图像二值化算法)
基本原理
均值法,选择的阈值是局部范围内像素的灰度均值(gray mean),该方法的一个变种是用常量C减去均值Mean,然后根据均值实现如下操作:
pixel = (pixel > (mean - c)) ? object : background
其中默认情况下参数C取值为0。object表示前景像素,background表示背景像素。
实现步骤
1. 彩色图像转灰度图像
2. 获取灰度图像的像素数据,预计算积分图
3. 根据输入的参数窗口半径大小从积分图中获取像素总和,求得平均值
4.循环每个像素,根据局部均值实现中心像素的二值化赋值
5.输入二值图像
运行结果:
代码实现:
package com.gloomyfish.ii.demo; import java.awt.image.BufferedImage; public class FastMeanBinaryFilter extends AbstractImageOptionFilter { private int constant; private int radius; public FastMeanBinaryFilter() { constant = 10; radius = 7; // 1,2,3,4,5,6,7,8 } public int getConstant() { return constant; } public void setConstant(int constant) { this.constant = constant; } public int getRadius() { return radius; } public void setRadius(int radius) { this.radius = radius; } @Override public BufferedImage process(BufferedImage image) { int width = image.getWidth(); int height = image.getHeight(); BufferedImage dest = createCompatibleDestImage( image, null ); // 图像灰度化 int[] inPixels = new int[width*height]; int[] outPixels = new int[width*height]; byte[] binData = new byte[width*height]; getRGB( image, 0, 0, width, height, inPixels ); int index = 0; 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; int gray= (int)(0.299 *tr + 0.587*tg + 0.114*tb); binData[index] = (byte)gray; } } // per-calculate integral image IntIntegralImage grayii = new IntIntegralImage(); grayii.setImage(binData); grayii.process(width, height); int yr = radius; int xr = radius; int size = (yr * 2 + 1)*(xr * 2 + 1); for (int row = 0; row < height; row++) { for (int col = 0; col < width; col++) { index = row * width + col; // 计算均值 int sr = grayii.getBlockSum(col, row, (yr * 2 + 1), (xr * 2 + 1)); int mean = sr / size; int pixel = binData[index]&0xff; // 二值化 if(pixel > (mean-constant)) { outPixels[row * width + col] = (0xff << 24) | (0xff << 16) | (0xff << 8) | 0xff; } else { outPixels[row * width + col] = (0xff << 24) | (0x00 << 16) | (0x00 << 8) | 0x00; } } } // 返回结果 setRGB(dest, 0, 0, width, height, outPixels); return dest; } }