Java图片上查找图片算法
作者:网络转载 发布时间:[ 2014/9/16 12:02:03 ] 推荐标签:软件开发 Java
下面附上算法完整java代码:
1 package com.jebysun.test.imagefind;
2
3 import java.awt.AWTException;
4 import java.awt.Rectangle;
5 import java.awt.Robot;
6 import java.awt.Toolkit;
7 import java.awt.image.BufferedImage;
8 import java.io.File;
9 import java.io.IOException;
10
11 import javax.imageio.ImageIO;
12 /**
13 * 屏幕上查找指定图片
14 * @author Jeby Sun
15 * @date 2014-09-13
16 * @website http://www.jebysun.com
17 */
18 public class ImageFindDemo {
19
20 BufferedImage screenShotImage; //屏幕截图
21 BufferedImage keyImage; //查找目标图片
22
23 int scrShotImgWidth; //屏幕截图宽度
24 int scrShotImgHeight; //屏幕截图高度
25
26 int keyImgWidth; //查找目标图片宽度
27 int keyImgHeight; //查找目标图片高度
28
29 int[][] screenShotImageRGBData; //屏幕截图RGB数据
30 int[][] keyImageRGBData; //查找目标图片RGB数据
31
32 int[][][] findImgData; //查找结果,目标图标位于屏幕截图上的坐标数据
33
34
35 public ImageFindDemo(String keyImagePath) {
36 screenShotImage = this.getFullScreenShot();
37 keyImage = this.getBfImageFromPath(keyImagePath);
38 screenShotImageRGBData = this.getImageGRB(screenShotImage);
39 keyImageRGBData = this.getImageGRB(keyImage);
40 scrShotImgWidth = screenShotImage.getWidth();
41 scrShotImgHeight = screenShotImage.getHeight();
42 keyImgWidth = keyImage.getWidth();
43 keyImgHeight = keyImage.getHeight();
44
45 //开始查找
46 this.findImage();
47
48 }
49
50 /**
51 * 全屏截图
52 * @return 返回BufferedImage
53 */
54 public BufferedImage getFullScreenShot() {
55 BufferedImage bfImage = null;
56 int width = (int) Toolkit.getDefaultToolkit().getScreenSize().getWidth();
57 int height = (int) Toolkit.getDefaultToolkit().getScreenSize().getHeight();
58 try {
59 Robot robot = new Robot();
60 bfImage = robot.createScreenCapture(new Rectangle(0, 0, width, height));
61 } catch (AWTException e) {
62 e.printStackTrace();
63 }
64 return bfImage;
65 }
66
67 /**
68 * 从本地文件读取目标图片
69 * @param keyImagePath - 图片路径
70 * @return 本地图片的BufferedImage对象
71 */
72 public BufferedImage getBfImageFromPath(String keyImagePath) {
73 BufferedImage bfImage = null;
74 try {
75 bfImage = ImageIO.read(new File(keyImagePath));
76 } catch (IOException e) {
77 e.printStackTrace();
78 }
79 return bfImage;
80 }
81
82 /**
83 * 根据BufferedImage获取图片RGB数组
84 * @param bfImage
85 * @return
86 */
87 public int[][] getImageGRB(BufferedImage bfImage) {
88 int width = bfImage.getWidth();
89 int height = bfImage.getHeight();
90 int[][] result = new int[height][width];
91 for (int h = 0; h < height; h++) {
92 for (int w = 0; w < width; w++) {
93 //使用getRGB(w, h)获取该点的颜色值是ARGB,而在实际应用中使用的是RGB,所以需要将ARGB转化成RGB,即bufImg.getRGB(w, h) & 0xFFFFFF。
94 result[h][w] = bfImage.getRGB(w, h) & 0xFFFFFF;
95 }
96 }
97 return result;
98 }
99
100
101 /**
102 * 查找图片
103 */
104 public void findImage() {
105 findImgData = new int[keyImgHeight][keyImgWidth][2];
106 //遍历屏幕截图像素点数据
107 for(int y=0; y<scrShotImgHeight-keyImgHeight; y++) {
108 for(int x=0; x<scrShotImgWidth-keyImgWidth; x++) {
109 //根据目标图的尺寸,得到目标图四个角映射到屏幕截图上的四个点,
110 //判断截图上对应的四个点与图B的四个角像素点的值是否相同,
111 //如果相同将屏幕截图上映射范围内的所有的点与目标图的所有的点进行比较。
112 if((keyImageRGBData[0][0]^screenShotImageRGBData[y][x])==0
113 && (keyImageRGBData[0][keyImgWidth-1]^screenShotImageRGBData[y][x+keyImgWidth-1])==0
114 && (keyImageRGBData[keyImgHeight-1][keyImgWidth-1]^screenShotImageRGBData[y+keyImgHeight-1][x+keyImgWidth-1])==0
115 && (keyImageRGBData[keyImgHeight-1][0]^screenShotImageRGBData[y+keyImgHeight-1][x])==0) {
116
117 boolean isFinded = isMatchAll(y, x);
118 //如果比较结果完全相同,则说明图片找到,填充查找到的位置坐标数据到查找结果数组。
119 if(isFinded) {
120 for(int h=0; h<keyImgHeight; h++) {
121 for(int w=0; w<keyImgWidth; w++) {
122 findImgData[h][w][0] = y+h;
123 findImgData[h][w][1] = x+w;
124 }
125 }
126 return;
127 }
128 }
129 }
130 }
131 }
132
133 /**
134 * 判断屏幕截图上目标图映射范围内的全部点是否全部和小图的点一一对应。
135 * @param y - 与目标图左上角像素点想匹配的屏幕截图y坐标
136 * @param x - 与目标图左上角像素点想匹配的屏幕截图x坐标
137 * @return
138 */
139 public boolean isMatchAll(int y, int x) {
140 int biggerY = 0;
141 int biggerX = 0;
142 int xor = 0;
143 for(int smallerY=0; smallerY<keyImgHeight; smallerY++) {
144 biggerY = y+smallerY;
145 for(int smallerX=0; smallerX<keyImgWidth; smallerX++) {
146 biggerX = x+smallerX;
147 if(biggerY>=scrShotImgHeight || biggerX>=scrShotImgWidth) {
148 return false;
149 }
150 xor = keyImageRGBData[smallerY][smallerX]^screenShotImageRGBData[biggerY][biggerX];
151 if(xor!=0) {
152 return false;
153 }
154 }
155 biggerX = x;
156 }
157 return true;
158 }
159
160 /**
161 * 输出查找到的坐标数据
162 */
163 private void printFindData() {
164 for(int y=0; y<keyImgHeight; y++) {
165 for(int x=0; x<keyImgWidth; x++) {
166 System.out.print("("+this.findImgData[y][x][0]+", "+this.findImgData[y][x][1]+")");
167 }
168 System.out.println();
169 }
170 }
171
172
173 public static void main(String[] args) {
174 String keyImagePath = "D:/key.png";
175 ImageFindDemo demo = new ImageFindDemo(keyImagePath);
176 demo.printFindData();
177 }
178
179 }
这种算法是精确比较,只要有一个像素点有差异,会找不到图片。当然,如果想指定一个比较的精确度,我也有个思路,是在算法步骤4比较映射范围内全部像素点的时候做个统计,如果90%的点都相同,那是说精确度是0.9。
另外,可能还要考虑效率问题,不过,我在我的应用场景中并不太在意效率。如果有朋友看到这篇文章,对这个话题有更好的想法,请留言。
本文内容不用于商业目的,如涉及知识产权问题,请权利人联系SPASVO小编(021-61079698-8054),我们将立即处理,马上删除。
相关推荐
Java性能测试有哪些不为众人所知的原则?Java设计模式??装饰者模式谈谈Java中遍历Map的几种方法Java Web入门必知你需要理解的Java反射机制知识总结编写更好的Java单元测试的7个技巧编程常用的几种时间戳转换(java .net 数据库)适合Java开发者学习的Python入门教程Java webdriver如何获取浏览器新窗口中的元素?Java重写与重载(区别与用途)Java变量的分类与初始化JavaScript有这几种测试分类Java有哪四个核心技术?给 Java开发者的10个大数据工具和框架Java中几个常用设计模式汇总java生态圈常用技术框架、开源中间件,系统架构及经典案例等

sales@spasvo.com