He escrito algunos asistentes de juegos usando el asistente de botones antes. Hay una función llamada FindPic, que busca una imagen determinada dentro del rango de la pantalla y devuelve la posición de las coordenadas encontradas.
Ahora, Java implementa una funcionalidad similar a esta función.
Descripción del algoritmo:
Tome una captura de pantalla y obtenga la imagen A (la imagen de destino que está buscando es la imagen B);
Recorra los píxeles de la imagen A y, según el tamaño de la imagen B, obtenga las cuatro esquinas de la imagen B asignadas a los cuatro puntos de la imagen A;
Los cuatro puntos obtenidos se comparan con los valores de los cuatro píxeles de las esquinas en la Figura B. Si los cuatro puntos son iguales, vaya al paso 4; de lo contrario, vuelva al paso 2 para continuar;
Para una mayor comparación, compare todos los puntos dentro del rango de mapeo con todos los puntos en la Figura B. Si son todos iguales, se ha encontrado la imagen; en caso contrario, vuelva al paso 2 para continuar;
Aquí, la comparación entre píxeles se realiza obteniendo el valor RGB de cada píxel a través del objeto BufferedImage. De la siguiente manera, convierta BufferedImage en una matriz bidimensional int:
/** * Obtener la matriz RGB de imágenes basada en BufferedImage * @param bfImage * @return */ public static int[][] getImageGRB(BufferedImage bfImage) { int width = bfImage.getWidth(); int height = bfImage.getHeight( ); int[][] resultado = nuevo int[alto][ancho]; = 0; h < height; h++) { for (int w = 0; w < width; w++) { //Utilice getRGB(w, h) para obtener el valor de color del punto, que es ARGB, pero en aplicaciones reales. , es RGB, por lo que ARGB debe convertirse a RGB, es decir, bufImg.getRGB (w, h) y 0xFFFFFF. resultado[h][w] = bfImage.getRGB(w, h) & 0xFFFFFF } } devolver resultado }
La comparación de si los valores RGB de dos píxeles son iguales se realiza mediante la operación XOR (que se dice que es más eficiente que ==. Si el valor obtenido después de la operación XOR es 0, significa que los valores RGB). de los dos píxeles son iguales; de lo contrario, no son iguales.
El código Java completo del algoritmo se adjunta a continuación:
paquete com.jebysun.test.imagefind; importar java.awt.AWTException; importar java.awt.Rectangle; importar java.awt.Robot; importar java.awt.image.BufferedImage; .File; import java.io.IOException; import javax.imageio.ImageIO /** * Encuentra la imagen especificada en la pantalla* @author; Jeby Sun * @date 2014-09-13 * @website http://www.jebysun.com */ public class ImageFindDemo { BufferedImage screenShotImage; // Captura de pantalla BufferedImage keyImage //Encontrar la imagen de destino int scrShotImgWidth // Ancho de captura de pantalla; int scrShotImgHeight; //Alto de la captura de pantalla int keyImgWidth; //Buscar el ancho de la imagen de destino int keyImgHeight; //Buscar la altura de la imagen de destino int[][] screenShotImageRGBData; //Captura de pantalla de datos RGB int[][] keyImageRGBData //Buscar resultados de la imagen de destino int[][][] findImgData; target Los datos de coordenadas del icono ubicado en la captura de pantalla public ImageFindDemo(String keyImagePath) { screenShotImage = this.getFullScreenShot(); = this.getBfImageFromPath(keyImagePath); screenShotImageRGBData = this.getImageGRB(screenShotImage); keyImageRGBData = this.getImageGRB(keyImage.getHeight(); keyImgWidth = keyImage.getWidth(); keyImgHeight = keyImage.getHeight(); //Comienza a buscar this.findImage(); = nulo; ancho entero = (int) Toolkit.getDefaultToolkit().getScreenSize().getWidth(); int altura = (int) Toolkit.getDefaultToolkit().getScreenSize().getHeight(); intente { Robot robot = new Robot(); nuevo Rectángulo (0, 0, ancho, alto)); captura (AWTException e) { e.printStackTrace(); } return bfImage; } /** * Leer la imagen de destino del archivo local * @param keyImagePath - la ruta absoluta de la imagen * @return el objeto BufferedImage de la imagen local */ public BufferedImage getBfImageFromPath (String keyImagePath) { BufferedImage bfImage = nulo; prueba { bfImage = ImageIO.read(nuevo File(keyImagePath)); } catch (IOException e) { e.printStackTrace(); return bfImage } /** * Obtener la matriz RGB de imagen basada en BufferedImage * @param bfImage * @return */ public int[][ ] getImageGRB (BufferedImage bfImage) { int ancho = bfImage.getWidth(); altura = bfImage.getHeight(); int[][] resultado = new int[altura][ancho] for (int h = 0; h < altura; h++) { for (int w = 0; w < ancho; w++ ) { //Utilice getRGB(w, h) El valor de color obtenido en este punto es ARGB, pero en aplicaciones reales se usa RGB, por lo que ARGB debe convertirse a RGB, es decir, bufImg.getRGB (w, h) & 0xFFFFFF. resultado[h][w] = bfImage.getRGB(w, h) & 0xFFFFFF; } } devolver resultado } /** * Buscar imágenes*/ public void findImage() { findImgData = new int[keyImgHeight][keyImgWidth][ 2]; //Recorre los datos de píxeles de la captura de pantalla for(int y=0; y<scrShotImgHeight-keyImgHeight; y++) { for(int x=0; ¿Son iguales los valores de los cuatro puntos y los cuatro píxeles de las esquinas de la Figura B? //Si son iguales, compare todos los puntos dentro del rango de mapeo en la captura de pantalla con todos los puntos de la imagen objetivo. 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) { booleano isFinded = isMatchAll(y, x); // Si los resultados de la comparación son exactamente iguales, significa que se encuentra la imagen y los datos de las coordenadas de posición encontradas se completan en la matriz de resultados de la búsqueda. 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; } } retorno; Determine si todos los puntos dentro del rango de mapeo de la imagen de destino en la captura de pantalla corresponden uno a uno a los puntos de la imagen pequeña. * @param y: la coordenada y de la captura de pantalla que desea coincidir con el punto de píxel en la esquina superior izquierda de la imagen de destino * @param x: la coordenada x de la captura de pantalla que desea coincidir con el punto de píxel en la esquina superior izquierda de la imagen de destino * @return */ public boolean isMatchAll(int y, int x) { int más grandeY = 0; int más grandeX = 0; int xor = 0 for(int más pequeñoY=0; más pequeñoY<keyImgHeight; más pequeñoY++) { más grandeY; = y+más pequeñoY; for(int más pequeñoX=0; más pequeñoX<keyImgWidth; más pequeñoX++) { más grandeX = x+más pequeñoX; if(biggerY>=scrShotImgHeight || más grandeX>=scrShotImgWidth) { return false } xor = keyImageRGBData[más pequeñoY][más pequeñoX; ]^screenShotImageRGBData[biggerY][biggerX]; if(xor!=0) { return false } } bigX = x } return true; /** * Genera los datos de coordenadas encontrados*/ private void printFindData() { for(int y=0; y<keyImgHeight; y++) { para(int x=0; x<keyImgWidth; x++) { System.out.print("("+this.findImgData[y][x][0]+", "+this.findImgData[y][x][1]+")"); println(); } } public static void main(String[] args) { String keyImagePath = "D:/key.png"; ImageFindDemo(keyImagePath); demo.printFindData();
Este algoritmo es una comparación precisa mientras haya una diferencia en un píxel, no se encontrará la imagen. Por supuesto, si desea especificar una precisión de comparación, también tengo una idea: hacer estadísticas al comparar todos los píxeles dentro del rango de mapeo en el paso 4 del algoritmo. Si el 90% de los puntos son iguales, eso significa. la precisión es 0,9.
Además, también se pueden considerar problemas de eficiencia, pero no me importa demasiado la eficiencia en el escenario de mi aplicación. Si algún amigo lee este artículo y tiene mejores ideas sobre este tema, deje un mensaje.