首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > 编程 >

JAVA兑现图片二值化

2013-01-05 
JAVA实现图片二值化??? 哎,项目要实现JAVA的图像二值化。纠结呀,在我影像中java对图像处理并不怎么好用,但

JAVA实现图片二值化

??? 哎,项目要实现JAVA的图像二值化。纠结呀,在我影像中java对图像处理并不怎么好用,但是没办法,成本要控制,只能拿出我们最大的法宝Google。没想到Google了一下,java集成的图像处理并没有我相像的那么难用,经过不断地尝试,项目也成功进入测试阶段,现将二值化方面信息拿出来和大家共享,也请大家指正。

?

一、首先说一下javax.imageio.ImageIO吧。

JDk版本

java version "1.6.0_02"
Java(TM) SE Runtime Environment (build 1.6.0_02-b06)
Java HotSpot(TM) Client VM (build 1.6.0_02-b06, mixed mode, sharing)

?

ImageIO可以处理的图像类型。

System.out.println(Arrays.asList(ImageIO.getReaderFormatNames()));

输出:[jpg, BMP, bmp, JPG, wbmp, jpeg, png, PNG, JPEG, WBMP, GIF, gif]

看可以看到JDK1.6通过ImageIO可以加载以上类型的图片。

?

二、通过BufferedImage来处理图片。

BufferedImage bi=ImageIO.read(new File("D:/Test/binary/test.jpg"));//通过imageio将图像载入int h=bi.getHeight();//获取图像的高int w=bi.getWidth();//获取图像的宽int rgb=bi.getRGB(0, 0);//获取指定坐标的ARGB的像素值

?可以看出通过BufferedImage 就可以轻松的获取图像的尺寸。

int BufferedImage.getRGB(x,y).获取到的是ARGB,最前面多了一个透明度。将返回的int转为16进制后,0-1透明度,2-3是R,4-5是G,6-7是B。

?

三、具体二值化的算法。

1、首先获取每个像素点的灰度值。目前使用简单的(R+G+B)/3

2、然后选定一个阀值。

3、将一个像素点灰度值和它周围的8个灰度值相加再除以9,然后和阀值比较。大于阀值的则置为255,小于则是0

?

四、废话少说,具体代码如下。

package image.binary;import java.awt.Color;import java.awt.image.BufferedImage;import java.io.File;import java.io.IOException;import javax.imageio.ImageIO;public class BinaryTest {public static void main(String[] args) throws IOException {BufferedImage bi=ImageIO.read(new File("D:/Test/binary/test.jpg"));//通过imageio将图像载入int h=bi.getHeight();//获取图像的高int w=bi.getWidth();//获取图像的宽int rgb=bi.getRGB(0, 0);//获取指定坐标的ARGB的像素值int[][] gray=new int[w][h];for (int x = 0; x < w; x++) {for (int y = 0; y < h; y++) {gray[x][y]=getGray(bi.getRGB(x, y));}}BufferedImage nbi=new BufferedImage(w,h,BufferedImage.TYPE_BYTE_BINARY);int SW=160;for (int x = 0; x < w; x++) {for (int y = 0; y < h; y++) {if(getAverageColor(gray, x, y, w, h)>SW){int max=new Color(255,255,255).getRGB();nbi.setRGB(x, y, max);}else{int min=new Color(0,0,0).getRGB();nbi.setRGB(x, y, min);}}}ImageIO.write(nbi, "jpg", new File("D:/Test/binary/二值化后_无压缩.jpg"));}public static int getGray(int rgb){String str=Integer.toHexString(rgb);int r=Integer.parseInt(str.substring(2,4),16);int g=Integer.parseInt(str.substring(4,6),16);int b=Integer.parseInt(str.substring(6,8),16);//or 直接new个color对象Color c=new Color(rgb);r=c.getRed();    g=c.getGreen();b=c.getBlue();int top=(r+g+b)/3;return (int)(top);}/** * 自己加周围8个灰度值再除以9,算出其相对灰度值 * @param gray * @param x * @param y * @param w * @param h * @return */public static int  getAverageColor(int[][] gray, int x, int y, int w, int h)    {        int rs = gray[x][y]                      + (x == 0 ? 255 : gray[x - 1][y])            + (x == 0 || y == 0 ? 255 : gray[x - 1][y - 1])            + (x == 0 || y == h - 1 ? 255 : gray[x - 1][y + 1])            + (y == 0 ? 255 : gray[x][y - 1])            + (y == h - 1 ? 255 : gray[x][y + 1])            + (x == w - 1 ? 255 : gray[x + 1][ y])            + (x == w - 1 || y == 0 ? 255 : gray[x + 1][y - 1])            + (x == w - 1 || y == h - 1 ? 255 : gray[x + 1][y + 1]);        return rs / 9;    }}

?

?

?相对较简单,将一个jpg图片二值化后产生一个无压缩的jpg文件。

?

?五、压缩

有些时候是需要将二值化后的图片进行压缩的,然后转成tiff格式的文件,以减少存储成本。但是jdk1.6的imageIO还没有加入TIFF格式的图像处理,那么可以使用辅助的包了。

1、jai-imageio包。目前发布的最新版本为1.1,1.2还在开发中。。

http://download.java.net/media/jai-imageio/builds/release/1_0_01/jai_imageio-1_0_01-windows-i586-jar.zip
2、解压后就两个jar包和一个dll。dll丢进PATH中,jar包放入工程,则我们就可以做压缩咯。

System.out.println(Arrays.asList(ImageIO.getWriterFormatNames()));

?看看,加入jar后的Imageio:

?[raw, tif, jpeg, JFIF, WBMP, jpeg-lossless, jpeg-ls, PNM, JPG, wbmp, PNG, JPEG, jpeg 2000, tiff, BMP, JPEG2000, RAW, JPEG-LOSSLESS, jpeg2000, GIF, TIF, TIFF, bmp, jpg, pnm, png, jfif, JPEG 2000, gif, JPEG-LS]

是不是可以处理的格式更强大了呢。。

?

3、压缩的全部代码。。

package image.binary;import java.awt.Color;import java.awt.image.BufferedImage;import java.io.File;import java.io.IOException;import javax.imageio.IIOImage;import javax.imageio.ImageIO;import javax.imageio.ImageWriteParam;import javax.imageio.ImageWriter;import javax.imageio.stream.ImageOutputStream;import com.sun.media.imageioimpl.plugins.tiff.TIFFImageWriterSpi;public class BinaryTest {public static void main(String[] args) throws IOException {BufferedImage bi=ImageIO.read(new File("D:/Test/binary/test.jpg"));//通过imageio将图像载入int h=bi.getHeight();//获取图像的高int w=bi.getWidth();//获取图像的宽int[][] gray=new int[w][h];for (int x = 0; x < w; x++) {for (int y = 0; y < h; y++) {gray[x][y]=getGray(bi.getRGB(x, y));}}BufferedImage nbi=new BufferedImage(w,h,BufferedImage.TYPE_BYTE_BINARY);int SW=160;for (int x = 0; x < w; x++) {for (int y = 0; y < h; y++) {if(getAverageColor(gray, x, y, w, h)>SW){int max=new Color(255,255,255).getRGB();nbi.setRGB(x, y, max);}else{int min=new Color(0,0,0).getRGB();nbi.setRGB(x, y, min);}}}TIFFImageWriterSpi tiffws=new TIFFImageWriterSpi();ImageWriter writer=tiffws.createWriterInstance();ImageWriteParam param=writer.getDefaultWriteParam();param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);param.setCompressionType("CCITT T.6");param.setCompressionQuality(0.8f);File outFile=new File("D:/Test/binary/二值化后_有压缩.tiff");ImageOutputStream ios=ImageIO.createImageOutputStream(outFile);writer.setOutput(ios);writer.write(null,new IIOImage(nbi, null, null), param);}public static int getGray(int rgb){String str=Integer.toHexString(rgb);int r=Integer.parseInt(str.substring(2,4),16);int g=Integer.parseInt(str.substring(4,6),16);int b=Integer.parseInt(str.substring(6,8),16);//or 直接new个color对象Color c=new Color(rgb);r=c.getRed();    g=c.getGreen();b=c.getBlue();int top=(r+g+b)/3;return (int)(top);}/** * 自己加周围8个灰度值再除以9,算出其相对灰度值 * @param gray * @param x * @param y * @param w * @param h * @return */public static int  getAverageColor(int[][] gray, int x, int y, int w, int h)    {        int rs = gray[x][y]                      + (x == 0 ? 255 : gray[x - 1][y])            + (x == 0 || y == 0 ? 255 : gray[x - 1][y - 1])            + (x == 0 || y == h - 1 ? 255 : gray[x - 1][y + 1])            + (y == 0 ? 255 : gray[x][y - 1])            + (y == h - 1 ? 255 : gray[x][y + 1])            + (x == w - 1 ? 255 : gray[x + 1][ y])            + (x == w - 1 || y == 0 ? 255 : gray[x + 1][y - 1])            + (x == w - 1 || y == h - 1 ? 255 : gray[x + 1][y + 1]);        return rs / 9;    }}

?

?

六、总结。。

1、效率问题还可以满足我们项目的要求,但是如果有同学想这样用的话一定要实际测试一下效率哦。

2、以及处理的图片效果。附件1.1版本的jai。

1 楼 feng5hao 2010-12-10   是否有考虑底色、底纹? 2 楼 mountain_king 2011-06-16   一般情况下,二值化主要针对文字、表格相应的图片。很少存在二值化后还要考虑其底色和底纹应该如何用黑白显示(只是个人理解)。。 3 楼 hxq131415 2011-09-04   楼主,怎么判断图片的明暗度呢? 4 楼 javajava22 2011-10-15   取出杂线的效果不是很理想呀,

热点排行