J'ai déjà écrit des assistants de jeu à l'aide de l'assistant de boutons. Il existe une fonction appelée FindPic, qui recherche une image donnée dans la plage de l'écran et renvoie la position des coordonnées trouvée.
Désormais, Java implémente des fonctionnalités similaires à cette fonction.
Description de l'algorithme :
Prenez une capture d'écran et obtenez l'image A (l'image cible que vous recherchez est l'image B) ;
Parcourez les pixels de l'image A, et selon la taille de l'image B, obtenez les quatre coins de l'image B mappés sur les quatre points de l'image A ;
Les quatre points obtenus sont comparés aux valeurs des quatre pixels de coin de la figure B. Si les quatre points sont identiques, passez à l'étape 4, sinon revenez à l'étape 2 pour continuer ;
Pour une comparaison plus approfondie, comparez tous les points de la plage de cartographie avec tous les points de la figure B. S'ils sont tous identiques, l'image a été trouvée ; sinon, revenez à l'étape 2 pour continuer ;
Ici, la comparaison entre les pixels se fait en obtenant la valeur RVB de chaque pixel via l'objet BufferedImage. Comme suit, convertissez BufferedImage en un tableau int bidimensionnel :
/** * Obtenez le tableau d'images RVB basé sur BufferedImage * @param bfImage * @return */ public static int[][] getImageGRB(BufferedImage bfImage) { int width = bfImage.getWidth(); ); int[][] résultat = nouveau int[hauteur][largeur] pour (int h = 0; h < height; h++) { for (int w = 0; w < width; w++) { //Utilisez getRGB(w, h) pour obtenir la valeur de couleur du point, qui est ARGB, mais dans des applications réelles , c'est RVB, donc ARVB doit être converti en RVB, c'est-à-dire bufImg.getRGB(w, h) & 0xFFFFFF. result[h][w] = bfImage.getRGB(w, h) & 0xFFFFFF; } } return result;
Comparer si les valeurs RVB de deux pixels sont identiques se fait via l'opération XOR (qui est dite plus efficace que == Si la valeur obtenue après l'opération XOR est 0, cela signifie que les valeurs RVB ). Des deux pixels sont identiques, sinon ce n'est pas pareil.
Le code Java complet de l’algorithme est joint ci-dessous :
package com.jebysun.test.imagefind ; importer java.awt.AWTException ; importer java.awt.Rectangle ; importer java.awt.Toolkit ; importer java.awt.image.BufferedImage ; .File; import java.io.IOException; import javax.imageio.ImageIO /** * Rechercher l'image spécifiée à l'écran* @author; Jeby Sun * @date 2014-09-13 * @website http://www.jebysun.com */ public class ImageFindDemo { BufferedImage screenShotImage; // Capture d'écran BufferedImage keyImage; // Rechercher l'image cible int scrShotImgWidth // Largeur de la capture d'écran int scrShotImgHeight; //Hauteur de la capture d'écran int keyImgWidth; //Rechercher la largeur de l'image cible int keyImgHeight; //Trouver la hauteur de l'image cible int[][] screenShotImageRGBData; //Capture d'écran RVB data int[][] keyImageRGBData; //Trouver les données RVB de l'image cible int[][][] findImgData; target Les données de coordonnées de l'icône située sur la capture d'écran public ImageFindDemo(String keyImagePath) { screenShotImage = this.getFullScreenShot(); = this.getBfImageFromPath(keyImagePath); screenShotImageRGBData = this.getImageGRB(screenShotImage); keyImageRGBData = this.getImageGRB(keyImage); scrShotImgWidth = screenShotImage.getWidth(); keyImgWidth = keyImage.getWidth(); keyImgHeight = keyImage.getHeight(); //Commencez à chercher this.findImage(); } /** * Capture d'écran plein écran* @return Return BufferedImage */ public BufferedImage getFullScreenShot() { BufferedImage bfImage = nul ; int largeur = (int) Toolkit.getDefaultToolkit().getScreenSize().getWidth(); int height = (int) Toolkit.getDefaultToolkit().getScreenSize().getHeight(); try { Robot robot = new Robot(); new Rectangle(0, 0, largeur, hauteur)); } catch (AWTException e) { e.printStackTrace(); } return bfImage; } /** * Lit l'image cible à partir du fichier local * @param keyImagePath - le chemin absolu de l'image * @return l'objet BufferedImage de l'image locale */ public BufferedImage getBfImageFromPath (String keyImagePath) { BufferedImage bfImage = null try { bfImage = ImageIO.read (nouveau ; File(keyImagePath)); } catch (IOException e) { e.printStackTrace(); } return bfImage; } /** * Obtenez le tableau d'images RVB basé sur BufferedImage * @param bfImage * @return */ public int[][ ] getImageGRB (BufferedImage bfImage) { int width = bfImage.getWidth(); hauteur = bfImage.getHeight(); int[][] résultat = new int[hauteur][largeur]; pour (int h = 0; h < hauteur; h++) { pour (int w = 0; w < largeur; w++ ) { //Utilisez getRGB(w, h) La valeur de couleur obtenue à ce stade est ARGB, mais dans les applications réelles, RVB est utilisé, donc ARVB doit être converti en RVB, c'est-à-dire bufImg.getRGB(w, h) & 0xFFFFFF. result[h][w] = bfImage.getRGB(w, h) & 0xFFFFFF; } } return result; } /** * Rechercher des images*/ public void findImage() { findImgData = new int[keyImgHeight][keyImgWidth][ 2]; //Parcourir les données de pixels de la capture d'écran pour(int y=0; y<scrShotImgHeight-keyImgHeight; y++) { for(int x=0; Les valeurs des quatre points et des quatre pixels de coin de la figure B sont-elles les mêmes ? //S'ils sont identiques, comparez tous les points dans la plage de mappage sur la capture d'écran avec tous les points de l'image cible. if((keyImageRGBData[0][0]^screenShotImageRGBData[y][x])==0 && (keyImageRGBData[0][keyImgWidth-1]^screenShotImageRGBData[y][x+keyImgWidth-1])==0 && (keyImageRGBData[keyImgHeight-1][keyImgWidth-1]^screenShotImageRGBData[y+keyImgHeight-1][x+keyImgWidth-1])==0 && (keyImageRGBData[keyImgHeight-1][0]^screenShotImageRGBData[y+keyImgHeight- 1][x])==0) { booléen isFinded = isMatchAll(y, x); //Si les résultats de la comparaison sont exactement les mêmes, cela signifie que l'image est trouvée et que les données de coordonnées de position trouvées sont remplies dans le tableau des résultats de recherche. if(isFinded) { for(int h=0; h<keyImgHeight; h++) { for(int w=0; w<keyImgWidth; w++) { findImgData[h][w][0] = y+h; h][w][1] = x+w; } } retour; } } } } } /** * Déterminez si tous les points situés dans la plage de mappage de l'image cible sur la capture d'écran correspondent aux points de la petite image un à un. * @param y - La coordonnée y de la capture d'écran qui veut correspondre au point de pixel dans le coin supérieur gauche de l'image cible * @param x - La coordonnée x de la capture d'écran qui veut correspondre au point de pixel dans le coin supérieur gauche de l'image cible * @return */ public boolean isMatchAll(int y, int x) { int plus grandY = 0; int plus grandX = 0; int plus petitY=0; plus petitY<keyImgHeight; plus petitY++) { plus grandY = y+plus petitY; pour(int plus petitX=0; plus petitX<keyImgWidth; plus petitX++) { plus grandX = x+plus petitX; if(plus petitY>=scrShotImgHeight || plus grandX>=scrShotImgWidth) { return false } xor = keyImageRGBData[plus petitY][plus petitX ]^screenShotImageRGBData[plus grandY][plus grandX]; if(xor!=0) { return false; } } bigX = x; return true } /** * Afficher les données de coordonnées trouvées*/ private void printFindData() { for(int y=0; y<keyImgHeight ; y++) { for(int x=0; x<keyImgWidth; x++) { System.out.print("("+this.findImgData[y][x][0]+", "+this.findImgData[y][x][1]+")" } System.out. println(); } } public static void main(String[] args) { String keyImagePath = "D:/key.png"; ImageFindDemo demo = new ImageFindDemo(keyImagePath); demo.printFindData();
Cet algorithme est une comparaison précise tant qu'il y a une différence d'un pixel, l'image ne sera pas trouvée. Bien sûr, si vous souhaitez spécifier une précision de comparaison, j'ai aussi une idée, qui est de faire des statistiques lors de la comparaison de tous les pixels dans la plage de cartographie à l'étape 4 de l'algorithme. Si 90 % des points sont identiques, cela signifie. la précision est de 0,9.
De plus, des problèmes d'efficacité peuvent également être pris en compte, mais je ne me soucie pas trop de l'efficacité dans mon scénario d'application. Si des amis lisent cet article et ont de meilleures idées sur ce sujet, veuillez laisser un message.