1. 程式人生 > >java實現圖像模版匹配(蝸牛學院)

java實現圖像模版匹配(蝸牛學院)

!= AS () The javaswing 需要 輸入 繼續 aca

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("測試失敗.");
		}
	}

}

  

java實現圖像模版匹配(蝸牛學院)