当前位置: 编程技术>java/j2ee
Java实现图片对比功能
来源: 互联网 发布时间:2014-11-07
本文导语: 之前用按键精灵写过一些游戏辅助,里面有个函数叫FindPic,就上在屏幕范围查找给定的一张图片,返回查找到的坐标位置。 现在,Java来实现这个函数类似的功能。 算法描述: 屏幕截图,得到图A,(查找的目标图...
之前用按键精灵写过一些游戏辅助,里面有个函数叫FindPic,就上在屏幕范围查找给定的一张图片,返回查找到的坐标位置。
现在,Java来实现这个函数类似的功能。
算法描述:
屏幕截图,得到图A,(查找的目标图片为图B);
遍历图A的像素点,根据图B的尺寸,得到图B四个角映射到图A上的四个点;
得到的四个点与图B的四个角像素点的值比较。如果四个点一样,执行步骤4;否则,回到步骤2继续;
进一步对比,将映射范围内的全部点与图B全部的点比较。如果全部一样,则说明图片已找到;否则,回到步骤2继续;
这里,像素之间的比较是通过BufferedImage对象获取每个像素的RGB值来比较的。如下,将BufferedImage转换为int二维数组:
/** * 根据BufferedImage获取图片RGB数组 * @param bfImage * @return */ public static int[][] getImageGRB(BufferedImage bfImage) { int width = bfImage.getWidth(); int height = bfImage.getHeight(); int[][] result = new int[height][width]; for (int h = 0; h < height; h++) { for (int w = 0; w < width; w++) { //使用getRGB(w, h)获取该点的颜色值是ARGB,而在实际应用中使用的是RGB,所以需要将ARGB转化成RGB,即bufImg.getRGB(w, h) & 0xFFFFFF。 result[h][w] = bfImage.getRGB(w, h) & 0xFFFFFF; } } return result; }
比较两个像素点的RGB值是否相同,是通过异或操作比较的(据说比==效率更高),如果异或操作后得到的值为0,说明两个像素点的RGB一样,否则不一样。
下面附上算法完整java代码:
package com.jebysun.test.imagefind; import java.awt.AWTException; import java.awt.Rectangle; import java.awt.Robot; import java.awt.Toolkit; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; import javax.imageio.ImageIO; /** * 屏幕上查找指定图片 * @author Jeby Sun * @date 2014-09-13 * @website http://www.jebysun.com */ public class ImageFindDemo { BufferedImage screenShotImage; //屏幕截图 BufferedImage keyImage; //查找目标图片 int scrShotImgWidth; //屏幕截图宽度 int scrShotImgHeight; //屏幕截图高度 int keyImgWidth; //查找目标图片宽度 int keyImgHeight; //查找目标图片高度 int[][] screenShotImageRGBData; //屏幕截图RGB数据 int[][] keyImageRGBData; //查找目标图片RGB数据 int[][][] findImgData; //查找结果,目标图标位于屏幕截图上的坐标数据 public ImageFindDemo(String keyImagePath) { screenShotImage = this.getFullScreenShot(); keyImage = this.getBfImageFromPath(keyImagePath); screenShotImageRGBData = this.getImageGRB(screenShotImage); keyImageRGBData = this.getImageGRB(keyImage); scrShotImgWidth = screenShotImage.getWidth(); scrShotImgHeight = screenShotImage.getHeight(); keyImgWidth = keyImage.getWidth(); keyImgHeight = keyImage.getHeight(); //开始查找 this.findImage(); } /** * 全屏截图 * @return 返回BufferedImage */ public BufferedImage getFullScreenShot() { BufferedImage bfImage = null; int width = (int) Toolkit.getDefaultToolkit().getScreenSize().getWidth(); int height = (int) Toolkit.getDefaultToolkit().getScreenSize().getHeight(); try { Robot robot = new Robot(); bfImage = robot.createScreenCapture(new Rectangle(0, 0, width, height)); } catch (AWTException e) { e.printStackTrace(); } return bfImage; } /** * 从本地文件读取目标图片 * @param keyImagePath - 图片绝对路径 * @return 本地图片的BufferedImage对象 */ public BufferedImage getBfImageFromPath(String keyImagePath) { BufferedImage bfImage = null; try { bfImage = ImageIO.read(new File(keyImagePath)); } catch (IOException e) { e.printStackTrace(); } return bfImage; } /** * 根据BufferedImage获取图片RGB数组 * @param bfImage * @return */ public int[][] getImageGRB(BufferedImage bfImage) { int width = bfImage.getWidth(); int height = bfImage.getHeight(); int[][] result = new int[height][width]; for (int h = 0; h < height; h++) { for (int w = 0; w < width; w++) { //使用getRGB(w, h)获取该点的颜色值是ARGB,而在实际应用中使用的是RGB,所以需要将ARGB转化成RGB,即bufImg.getRGB(w, h) & 0xFFFFFF。 result[h][w] = bfImage.getRGB(w, h) & 0xFFFFFF; } } return result; } /** * 查找图片 */ public void findImage() { findImgData = new int[keyImgHeight][keyImgWidth][2]; //遍历屏幕截图像素点数据 for(int y=0; y