模擬按鍵精靈 FindPic 功能:在屏幕截圖中查找指定目標圖片,返回匹配坐標。應用於自動化測試、遊戲輔助、RPA 機器人。
// BufferedImage.getRGB() 返回 ARGB (含透明通道)
// 需屏蔽 Alpha 通道:& 0xFFFFFF
int rgb = image.getRGB(x, y) & 0xFFFFFF;
// 像素相等判斷:異或運算
// a ^ b == 0 當且僅當 a == b
// 比 equals() 更快,避免對象創建
if ((pixelA ^ pixelB) == 0) { /* 匹配 */ }
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
public class ImageFinder {
private final int[][] screenRGB; // 屏幕像素數組 [y][x]
private final int[][] targetRGB; // 目標像素數組
private final int screenW, screenH;
private final int targetW, targetH;
public ImageFinder(String targetImagePath) throws AWTException, IOException {
// 1. 全屏截圖
BufferedImage screen = new Robot().createScreenCapture(
new Rectangle(Toolkit.getDefaultToolkit().getScreenSize()));
// 2. 讀取目標圖片
BufferedImage target = ImageIO.read(new File(targetImagePath));
// 3. 轉換為 RGB 數組
this.screenRGB = toRGBArray(screen);
this.targetRGB = toRGBArray(target);
this.screenW = screen.getWidth();
this.screenH = screen.getHeight();
this.targetW = target.getWidth();
this.targetH = target.getHeight();
}
private int[][] toRGBArray(BufferedImage img) {
int w = img.getWidth(), h = img.getHeight();
int[][] rgb = new int[h][w];
for (int y = 0; y < h; y++) {
for (int x = 0; x < w; x++) {
rgb[y][x] = img.getRGB(x, y) & 0xFFFFFF;
}
}
return rgb;
}
public Point find() {
for (int y = 0; y <= screenH - targetH; y++) {
for (int x = 0; x <= screenW - targetW; x++) {
// 四角快速過濾
if (matchFourCorners(x, y) && matchAllPixels(x, y)) {
return new Point(x, y); // 返回左上角坐標
}
}
}
return null; // 未找到
}
private boolean matchFourCorners(int x, int y) {
return (targetRGB[0][0] ^ screenRGB[y][x]) == 0 &&
(targetRGB[0][targetW-1] ^ screenRGB[y][x+targetW-1]) == 0 &&
(targetRGB[targetH-1][targetW-1] ^ screenRGB[y+targetH-1][x+targetW-1]) == 0 &&
(targetRGB[targetH-1][0] ^ screenRGB[y+targetH-1][x]) == 0;
}
private boolean matchAllPixels(int x, int y) {
for (int ty = 0; ty < targetH; ty++) {
for (int tx = 0; tx < targetW; tx++) {
if ((targetRGB[ty][tx] ^ screenRGB[y+ty][x+tx]) != 0) {
return false;
}
}
}
return true;
}
public static void main(String[] args) throws Exception {
ImageFinder finder = new ImageFinder("D:/target.png");
Point pt = finder.find();
if (pt != null) {
System.out.println("找到圖片於: (" + pt.x + ", " + pt.y + ")");
} else {
System.out.println("未找到目標圖片");
}
}
}
| 優化點 | 說明 | 預期提升 |
|---|---|---|
| 縮放金字塔 | 多尺度匹配,先在縮小圖定位大致區域 | 10-100x |
| 特徵點匹配 (ORB/SIFT) | 不依賴像素完全相同,抗縮放/旋轉/光照變化 | 質的飛躍 |
| ROI 區域限制 | 業務邏輯限定搜索區域 (如遊戲特定窗口) | 線性縮減 |
| 並行化 | ForkJoinPool 分塊並行搜索 | CPU 核心數倍 |
| OpenCV/JavaCV | 調用 C++ 優化的 matchTemplate (TM_CCOEFF_NORMED) | 100-1000x |
// 在 matchAllPixels 中統計匹配像素比例
int matchCount = 0;
int total = targetW * targetH;
for (...) {
if ((targetRGB[ty][tx] ^ screenRGB[y+ty][x+tx]) == 0) matchCount++;
}
double similarity = (double) matchCount / total;
if (similarity >= 0.95) return new Point(x, y); // 95% 相似度閾值
SetProcessDPIAware() 或 JNA 調用像素級精確匹配適合 UI 自動化、固定界面識別場景。複雜場景建議引入 OpenCV 特徵匹配或深度學習目標檢測。