在这段时间中,我们的软件杯比赛项目中,我进行了对图片的处理,尽可能的来实现我们识别的准确性,我的图片处理总的分为两个部分:
第一部分:我们把图片的水印去掉了,由于我们的图片是.png格式的,他的特点在于,这类图片是透明背景,字体的颜色是黑色,而水印的颜色是白色,所以我们首先遍历所有像素,计算一下整张图的灰度的平均值(grayMean),轮廓颜色较深,灰度值比较小,背景颜色较浅,灰度值较大,加权平均之后总的平均值会比背景的灰度值略低,然后再次遍历所有像素,并计算每个像素点的灰度,如果其灰度值比grayMean大,则将其alpha值设为0,即完全透明,否则不做处理。
代码:
public BufferedImage alphaProcess(BufferedImage bufferedImage) { //获取源图像的宽高 int width = bufferedImage.getWidth(); int height = bufferedImage.getHeight(); System.out.println(width+" "+height); //实例化一个同样大小的图片,并将type设为 BufferedImage.TYPE_4BYTE_ABGR,支持alpha通道的rgb图像 BufferedImage resImage = new BufferedImage(width, height, BufferedImage.TYPE_4BYTE_ABGR); double grayMean = 0; for (int i = 0; i < width; i++) { for (int j = 0; j < height; j++) { int rgb = bufferedImage.getRGB(i,j); int r = (0xff&rgb); int g = (0xff&(rgb>>8)); int b = (0xff&(rgb>>16)); //这是灰度值的计算公式 grayMean += (r*0.299+g*0.587+b*0.114); } } //计算平均灰度 grayMean = grayMean/(width*height); for (int i = 0; i < width; i++) { for (int j = 0; j < height; j++) { int rgb = bufferedImage.getRGB(i,j); //一个int是32位,java中按abgr的顺序存储,即前8位是alpha,最后8位是r,所以可以通过下面的方式获取到rgb的值 int r = (0xff&rgb); int g = (0xff&(rgb>>8)); int b = (0xff&(rgb>>16)); double gray = (r*0.299+g*0.587+b*0.114); //如果灰度值大于之前求的平均灰度值,则将其alpha设为0,下面准确写应该是rgb = r + (g << 8) + (b << 16) + (0 << 24); if (gray>grayMean){ rgb = r + (g << 8) + (b << 16); } resImage.setRGB(i,j,rgb); } } //ok,返回的就是将浅色背景设为透明的BufferedImage了,可以用灰度化里提到的方式写成文件 return resImage; }
第二部分为:改变图片的格式,在进行是被的过程中,我发现当我将.png格式的图片转换为.jpg格式图片后,他的识别正确率是提高的。
代码:
private static void writeBufferedImage(BufferedImage img,String filePath){ String format = filePath.substring(filePath.indexOf('.')+1); //获取图片格式 System.out.println(format); try { ImageIO.write(img,format,new File(filePath)); } catch (IOException e) { e.printStackTrace(); } }
在经过这两次的图片处理后,我们的图片的识别正确率有很大的提高
结果截图:
未进行处理之前的图片:
进行处理之后的图片: