zoukankan      html  css  js  c++  java
  • java实现图像模版匹配(蜗牛学院)

    package com.woniu.test;
    
    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 javax.imageio.ImageIO;
    //java图像模版匹配
    //核心思路:用一张小图片,在一张大图片里去寻找,并返回该小图片所在的坐标位置,然后将鼠标移向该处,并实施相应操作。并更据页面的反馈,进行相应的判断(断言)
    //1.对需要操作的对象进行截图,得到一张小图片,并保存。
    //2.对当前屏幕进行截图,获得一张大图片,保存或放在内存中
    //3.利用模版匹配,在大图片中,按像素对小图片进行滑动,找到小图片所在的位置。
    //4.对该坐标位置(X,Y),加上小图片高度的一半(H),宽度的一般(W),得到该小图片的中心位置,即是我们要操作的坐标(X+W,Y+H)
    //5。将鼠标移向该坐标(X,Y),并进行相应操作(输入,单机,双击,右键等).
    //6.继续第二轮操作,第三轮操作。直到第N轮。最后进行模版匹配,来确认是否存在和预期结果一致的小图片,进而实现断言。
    //由于是基于的像素匹配,所以,如果界面风格发生变化,可能出现识别不到的情况。
    public class ImageMatch {
    
    	public static void main(String[] args) throws Exception {
    		ImageMatch im = new ImageMatch();
    //		BufferedImage bi = im.getScreenShot();
    //		int[][] result = im.getImageRGB(bi);
    //		for (int y = 0; y < result.length; y++) {
    //			for (int x = 0; x < result[y].length; x++) {
    //				System.out.println(result[y][x]);
    //			}
    //		}
    		Runtime.getRuntime().exec("C:/Windows/system32/calc.exe");
    		Thread.sleep(3000);
    		
    		String imageDir = System.getProperty("user.dir") + "/wincalc/";
    		int[] target = im.findImage(imageDir + "3.png");
    		System.out.println("找到一个点:" + target[0] + " : " + target[1]);
    	}
    
    	// 截图
    	public BufferedImage getScreenShot() {
    		BufferedImage bfImage = null;
    		int captureWidth = (int)Toolkit.getDefaultToolkit().getScreenSize().getWidth();
    		int captureHeight = (int)Toolkit.getDefaultToolkit().getScreenSize().getHeight();
    		try {
    			Robot robot = new Robot();
    			Rectangle screenRect = new Rectangle(0,0,captureWidth,captureHeight);
    			bfImage = robot.createScreenCapture(screenRect);
    		} catch (AWTException e) {
    			e.printStackTrace();
    		}
    		return bfImage;
    	}
    	
    	// 获取像素点值
    	public int[][] getImageRGB(BufferedImage bfImage) {
    		int width = bfImage.getWidth();
    		int height = bfImage.getHeight();
    		int[][] result = new int[width][height];
    		for (int y = 0; y < height; y++) {
    			for (int x = 0; x < width; x++) {
    				// 对某个像素点的RGB编码并存入数据库
    				result[x][y] = bfImage.getRGB(x, y) & 0xFFFFFF;
    				//单独获取每一个像素点的Red,Green,和Blue的值。
    				//int r = (bfImage.getRGB(x, y) & 0xFF0000) >> 16;
    				//int g = (bfImage.getRGB(x, y) & 0xFF00) >> 8;
    				//int b = bfImage.getRGB(x, y) & 0xFF;
    			}
    		}
    		return result;
    	}
    	
    	// 进行模板匹配
    	public int[] findImage(String imagePath) {
    		BufferedImage bigImage = this.getScreenShot();	// 当前屏幕截图
    		BufferedImage smallImage = null;		// 打开预选保存的小图片
    		try {
    			smallImage = ImageIO.read(new File(imagePath));
    		} catch (Exception e) {
    			e.printStackTrace();
    		}
    		
    		int bigWidth = bigImage.getWidth();
    		int bigHeight = bigImage.getHeight();
    		
    		int smallWidth = smallImage.getWidth();
    		int smallHeight = smallImage.getHeight();
    		
    		int[][] bigData = this.getImageRGB(bigImage);
    		int[][] smallData = this.getImageRGB(smallImage);
    		
    		int[] target = {-1, -1};
    		
    		for (int y=0; y<bigHeight-smallHeight; y++) {
    			for (int x=0; x<bigWidth-smallWidth; x++) {
    				// 对关键点进行先期匹配,降低运算复杂度。如果关键点本身就不匹配,就没必要再去匹配小图的每一个像素点。
    				if (bigData[x][y] == smallData[0][0] &&   // 左上角
    					bigData[x+smallWidth-1][y] == smallData[smallWidth-1][0] &&  // 右上角
    					bigData[x][y+smallHeight-1] == smallData[0][smallHeight-1] && // 左下角
    					bigData[x+smallWidth-1][y+smallHeight-1] == smallData[smallWidth-1][smallHeight-1] && // 右下角
    					bigData[x+smallWidth/2][y+smallHeight/2] == smallData[smallWidth/2][smallHeight/2]
    					) {
    					// 进行全像素匹配
    					boolean isMatched = this.checkAllMatch(x, y, smallHeight, smallWidth, bigData, smallData);
    					if (isMatched) {
    						System.out.println("像素点X" + x + " : Y" + y + ",对应的值为:" + bigData[x][y]);
    						// 获取小图的中心位置的点
    						int centerX = x + smallWidth/2;
    						int centerY = y + smallHeight/2;
    						target[0] = centerX;
    						target[1] = centerY;
    						return target;
    					}
    				}
    			}
    		}
    		
    		return target;
    	}
    	
    	// 全像素匹配
    	public boolean checkAllMatch(int x, int y, int smallHeight, int smallWidth, int[][] bigData, int[][] smallData) {
    		boolean isMatched = true;
    		for (int smallY=0; smallY<smallHeight; smallY++) {
    			for (int smallX=0; smallX<smallWidth; smallX++) {
    				// 如果发现有一个像素点,两者的值不一样,则认为不相等,如果不相等,则没必要继续比较其它点.
    				if (bigData[x+smallX][y+smallY] != smallData[smallX][smallY]) {
    					isMatched = false;
    					return isMatched;
    				}
    			}
    		}
    		return isMatched;
    	}
    }
    
    package com.woniu.test;
    
    public class CalcTestDemo {
    
    	static AutoTestRobot robot = new AutoTestRobot();
    	
    	public static void main(String[] args) throws Exception {
    		
    		Runtime.getRuntime().exec("java -jar D:/Other/JavaSwingCalc.jar");
    		Thread.sleep(3000);
    		
    		String imageDir = System.getProperty("user.dir") + "/javacalc/";
    		
    		robot.moveAndInput(imageDir + "numberx.png", "300");
    		robot.moveAndInput(imageDir + "numbery.png", "200");
    		robot.moveAndSelect(imageDir + "calctype.png", 1);
    		robot.moveAndClick(imageDir + "docalc.png");
    		
    		if (robot.isExists(imageDir + "result.png")) {
    			System.out.println("测试成功.");
    		}
    		else {
    			System.out.println("测试失败.");
    		}
    	}
    
    }
    

      

    TryEverything
  • 相关阅读:
    XML常用操作
    关于C#的单斜杆和双斜杆
    XX驱动保护之KdDisableDebugger
    提供程序未返回 ProviderManifestToken 字符串 解决方案
    C# int转short
    C#_混淆/反混淆,逆向/反逆向之Dotfuscator
    mouseout和mouseover、mouseenter和mouseleave
    输入法下keypress、keyup失效的解决方案
    linux常用基本命令
    如何把已完成的项目部署到服务器
  • 原文地址:https://www.cnblogs.com/LiTry/p/9038579.html
Copyright © 2011-2022 走看看