Já escrevi alguns assistentes de jogo usando o assistente de botão. Existe uma função chamada FindPic, que procura uma determinada imagem dentro do intervalo da tela e retorna a posição da coordenada encontrada.
Agora, Java implementa funcionalidade semelhante a esta função.
Descrição do algoritmo:
Faça uma captura de tela e obtenha a imagem A (a imagem alvo que você está procurando é a imagem B);
Percorra os pixels da imagem A e, de acordo com o tamanho da imagem B, obtenha os quatro cantos da imagem B mapeados nos quatro pontos da imagem A;
Os quatro pontos obtidos são comparados com os valores dos quatro pixels dos cantos da Figura B. Se os quatro pontos forem iguais, vá para o passo 4, caso contrário, volte para o passo 2 para continuar;
Para comparação adicional, compare todos os pontos dentro do intervalo de mapeamento com todos os pontos da Figura B. Se forem todas iguais, a imagem foi encontrada; caso contrário, volte ao passo 2 para continuar;
Aqui, a comparação entre pixels é feita obtendo o valor RGB de cada pixel através do objeto BufferedImage. Como segue, converta BufferedImage em um array bidimensional int:
/** * Obtenha o array RGB da imagem com base em BufferedImage * @param bfImage * @return */ public static int[][] getImageGRB(BufferedImage bfImage) { int width = bfImage.getWidth(); ); int[][] resultado = new int[altura][largura]; = 0; h < height; h++) { for (int w = 0; w < width; w++) { //Use getRGB(w, h) para obter o valor da cor do ponto, que é ARGB, mas em aplicações reais , é RGB, então ARGB precisa ser convertido em RGB, ou seja, bufImg.getRGB(w, h) & 0xFFFFFF. resultado[h][w] = bfImage.getRGB(w, h) & 0xFFFFFF;
Comparar se os valores RGB de dois pixels são iguais é feito através da operação XOR (que é considerada mais eficiente que ==). Se o valor obtido após a operação XOR for 0, significa que os valores RGB ). dos dois pixels são iguais, caso contrário não é o mesmo.
O código java completo do algoritmo está anexado abaixo:
pacote com.jebysun.test.imagefind; importar java.awt.AWTException; importar java.awt.Rectangle; .File; import java.io.IOException; import javax.imageio.ImageIO; Jeby Sun * @data 13/09/2014 * @website http://www.jebysun.com */ public class ImageFindDemo { BufferedImage screenShotImage; //Captura de tela BufferedImage keyImage; //Encontre a imagem de destino int scrShotImgWidth; int scrShotImgHeight; //Altura da captura de tela int keyImgWidth; //Encontre a largura da imagem alvo int keyImgHeight; //Encontrar a altura da imagem alvo int[][] screenShotImageRGBData; //Captura de tela dos dados RGB int[][] keyImageRGBData; alvo Os dados de coordenadas do ícone localizado na captura de tela public ImageFindDemo(String keyImagePath) { screenShotImage = this.getFullScreenShot(); = this.getBfImageFromPath(keyImagePath); screenShotImageRGBData = this.getImageGRB(screenShotImage); keyImageRGBData = this.getImageGRB(keyImageWidth = screenShotImage.getWidth(); keyImgWidth = keyImage.getWidth(); keyImgHeight = keyImage.getHeight(); //Comece a procurar por this.findImage(); = nulo; largura interna = (int) Toolkit.getDefaultToolkit().getScreenSize().getWidth(); int height = (int) Toolkit.getDefaultToolkit().getScreenSize().getHeight(); new Rectangle(0, 0, largura, altura)); { e.printStackTrace(); return bfImage } /** * Ler a imagem de destino do arquivo local * @param keyImagePath - o caminho absoluto da imagem * @return o objeto BufferedImage da imagem local */ public BufferedImage getBfImageFromPath (String keyImagePath) { BufferedImage bfImage = null; tente { bfImage = ImageIO.read (new; File(keyImagePath)); catch (IOException e) { e.printStackTrace(); return bfImage } /** * Obtenha o array RGB da imagem com base em BufferedImage * @param bfImage * @return */ public int[][ ] getImageGRB (BufferedImage bfImage) {int largura = bfImage.getWidth(); altura = bfImage.getHeight(); int[][] resultado = new int[altura][largura]; ) { //Use getRGB(w, h) O valor da cor obtido neste ponto é ARGB, mas em aplicações reais é usado RGB, então ARGB precisa ser convertido em RGB, ou seja, bufImg.getRGB(w, h) & 0xFFFFFF. result[h][w] = bfImage.getRGB(w, h) & 0xFFFFFF; } } return resultado } /** * Encontrar imagens*/ public void findImage() { findImgData = new int[keyImgHeight][keyImgWidth][ 2]; //Percorre os dados do pixel da captura de tela for(int y=0; y<scrShotImgHeight-keyImgHeight; y++) { for(int x=0; Os valores dos quatro pontos e dos quatro pixels dos cantos da Figura B são iguais? //Se forem iguais, compare todos os pontos dentro do intervalo de mapeamento na captura de tela com todos os pontos da imagem alvo. 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); //Se os resultados da comparação forem exatamente iguais, significa que a imagem foi encontrada e os dados de coordenadas de posição encontrados são preenchidos na matriz de resultados da pesquisa. if(isFinded) { for(int h=0; h<keyImgHeight; h++) { for(int w=0; w<keyImgWidth; w++) { findImgData[h][w][0] = y+hData[; h][w][1] = x+w } } retornar; Determine se todos os pontos dentro do intervalo de mapeamento da imagem alvo na captura de tela correspondem aos pontos da imagem pequena, um a um. * @param y - A coordenada y da captura de tela que deseja corresponder ao ponto de pixel no canto superior esquerdo da imagem alvo * @param x - A coordenada x da captura de tela que deseja corresponder ao ponto de pixel no canto superior esquerdo da imagem alvo * @return */ public boolean isMatchAll(int y, int x) { int maiorY = 0 int maiorX = 0 for(int menorY=0; menorY<keyImgHeight; menorY++) { maiorY; = y+menorY; for(int menorX=0; menorX<keyImgWidth; menorX++) { maiorX = x+menorX; if(maiorY>=scrShotImgHeight || maiorX>=scrShotImgWidth) { return false } xor = keyImageRGBData[menorY][menorX ]^screenShotImageRGBData[biggerY][biggerX]; if(xor!=0) { return false } } largeX = x } return true } /** * Produz os dados de coordenadas encontrados*/ 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]+")"); println(); } } public static void main(String[] args) { String keyImagePath = "D:/key.png"; ImageFindDemo(keyImagePath);
Este algoritmo é uma comparação precisa. Enquanto houver uma diferença em um pixel, a imagem não será encontrada. Claro, se você quiser especificar uma precisão de comparação, também tenho uma ideia, que é fazer estatísticas ao comparar todos os pixels dentro do intervalo de mapeamento na etapa 4 do algoritmo. Se 90% dos pontos forem iguais, isso significa. a precisão é de 0,9.
Além disso, questões de eficiência também podem ser consideradas, mas não me importo muito com a eficiência no meu cenário de aplicação. Se algum amigo ler este artigo e tiver ideias melhores sobre o assunto, deixe uma mensagem.