Java图片比对


 

 在自动化测试中,除了普通的值验证,经常还有一些图片验证,比如图片的匹配率,输出图片的差异图片等。本文主要用到了BufferedImage类来操作图片比对和输出差异图片,大体的思路如下:

1. 通过ImageIO读入图片,生成相应的BufferedImage实例(Image操作流)

2. 修改目标图片的尺寸大小,以适应期望图片的大小(为像素比对做准备)

3. 获取每一个(width,height)的ARGB,并获取相应的Red, Green,Blue的值

4. 按照每个像素点的R,G,B进行比较(需要定义允许的R,G,B的误差)

5. 统计不同的像素点,生成diff图片

代码如下:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 import javax.imageio.ImageIO; import java.awt.*; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; import java.text.DecimalFormat;     public class ImageDiff {       //不同的像素标记为红色     public static final int RGB_RED = 16711680;       //允许的Red,Green,Blue单个维度的像素差值     public static final int DIFF_ALLOW_RANGE = 5;       //不同像素点统计值     public static int diffPointCount = 0;       //从rgb值中抽取red     public static int getRed(int rgbValue){         return rgbValue & 0xff0000 >> 16;     }       //从rgb值中抽取green     public static int getGreen(int rgbValue){         return rgbValue & 0xff00 >> 8;     }       //从rgb值中抽取blue     public static int getBlue(int rgbValue){         return rgbValue & 0xff;     }       /**      * 比较两图片,并用红色标出不同的像素点,然后保存差异图片到本地,打印匹配率      * @param srcImgPath      * @param targetImgPath      */     public static void compareImages(String srcImgPath,String targetImgPath){         try {             BufferedImage srcImg = ImageIO.read(new File(srcImgPath));             BufferedImage targetImg = ImageIO.read(new File(targetImgPath));               diffPointCount = 0;             BufferedImage diffImg = srcImg;               int srcHeight = srcImg.getHeight();             int srcWidth = srcImg.getWidth();               //修改待比较图片的尺寸以适应源图片的尺寸             targetImg = changeImageSize(targetImg,srcHeight,srcWidth);               int srcRgb;             int targetRgb;               for(int h = 0;h                 for(int w=0;w                     srcRgb = srcImg.getRGB(w,h);                     targetRgb = targetImg.getRGB(w,h);                     if( Math.abs(getRed(srcRgb) - getRed(targetRgb))>DIFF_ALLOW_RANGE ||                             Math.abs(getGreen(srcRgb) - getGreen(targetRgb))>DIFF_ALLOW_RANGE||                             Math.abs(getBlue(srcRgb) - getBlue(targetRgb))>DIFF_ALLOW_RANGE){                         diffImg.setRGB(w,h, RGB_RED);                         diffPointCount++;                     }                 }             }               //保存差异图片             ImageIO.write(diffImg,"jpg",new File("diffImg.jpg"));             System.out.println("保存差异图片成功!");               //计算相似度(保留小数点后四位)             int totalPixel = srcHeight*srcWidth;             DecimalFormat decimalFormat = new DecimalFormat("#.####");             double matchRate = (totalPixel-diffPointCount)/(totalPixel*1.0);               System.out.println("图片相似度为: "+decimalFormat.format(matchRate)+"%");           }catch (Exception ex){             ex.printStackTrace();         }     }         /**      * 修改BufferedImage中的图片尺寸,以便和源图片进行比较      * @param image      * @param newHeight      * @param newWidth      * @return      */     public static BufferedImage changeImageSize(BufferedImage image,int newHeight,int newWidth){         Image img = image.getScaledInstance(newWidth,newHeight,Image.SCALE_SMOOTH);         int width = img.getWidth(null);         int height = img.getHeight(null);           //获取新图片的BufferedImage实例         BufferedImage newBufferedImage = new BufferedImage(width, height,                 BufferedImage.TYPE_INT_ARGB);         Graphics g = newBufferedImage.getGraphics();         g.drawImage(img, 00null);         g.dispose();         return newBufferedImage;     }       public static void main(String[] args){         compareImages("1.jpg","2.jpg");     } }

参考: