国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

Java圖片上查找圖片算法

2019-11-14 21:08:41
字體:
來源:轉載
供稿:網友
java圖片上查找圖片算法

  之前用按鍵精靈寫過一些游戲輔助,里面有個函數叫FindPic,就是在屏幕范圍查找給定的一張圖片,返回查找到的坐標位置。

  現在,Java來實現這個函數類似的功能。

  算法描述:

  1. 屏幕截圖,得到圖A,(查找的目標圖片為圖B);
  2. 遍歷圖A的像素點,根據圖B的尺寸,得到圖B四個角映射到圖A上的四個點;
  3. 得到的四個點與圖B的四個角像素點的值比較。如果四個點一樣,執行步驟4;否則,回到步驟2繼續;
  4. 進一步對比,將映射范圍內的全部點與圖B全部的點比較。如果全部一樣,則說明圖片已找到;否則,回到步驟2繼續;

  這里,像素之間的比較是通過BufferedImage對象獲取每個像素的RGB值來比較的。如下,將BufferedImage轉換為int二維數組:

 1     /** 2      * 根據BufferedImage獲取圖片RGB數組 3      * @param bfImage 4      * @return 5      */ 6     public static int[][] getImageGRB(BufferedImage bfImage) { 7         int width = bfImage.getWidth(); 8         int height = bfImage.getHeight(); 9         int[][] result = new int[height][width];10         for (int h = 0; h < height; h++) {11             for (int w = 0; w < width; w++) {12                 //使用getRGB(w, h)獲取該點的顏色值是ARGB,而在實際應用中使用的是RGB,所以需要將ARGB轉化成RGB,即bufImg.getRGB(w, h) & 0xFFFFFF。13                 result[h][w] = bfImage.getRGB(w, h) & 0xFFFFFF;14             }15         }16         return result;17     }

  比較兩個像素點的RGB值是否相同,是通過異或操作比較的(據說比==效率更高),如果異或操作后得到的值為0,說明兩個像素點的RGB一樣,否則不一樣。

  下面附上算法完整java代碼:

  1 package com.jebysun.test.imagefind;  2   3 import java.awt.AWTException;  4 import java.awt.Rectangle;  5 import java.awt.Robot;  6 import java.awt.Toolkit;  7 import java.awt.image.BufferedImage;  8 import java.io.File;  9 import java.io.IOException; 10  11 import javax.imageio.ImageIO; 12 /** 13  * 屏幕上查找指定圖片 14  * @author Jeby Sun 15  * @date 2014-09-13 16  * @website http://www.jebysun.com 17  */ 18 public class ImageFindDemo { 19      20     BufferedImage screenShotImage;    //屏幕截圖 21     BufferedImage keyImage;           //查找目標圖片 22      23     int scrShotImgWidth;              //屏幕截圖寬度 24     int scrShotImgHeight;             //屏幕截圖高度 25      26     int keyImgWidth;                  //查找目標圖片寬度 27     int keyImgHeight;                 //查找目標圖片高度 28      29     int[][] screenShotImageRGBData;   //屏幕截圖RGB數據 30     int[][] keyImageRGBData;          //查找目標圖片RGB數據 31      32     int[][][] findImgData;            //查找結果,目標圖標位于屏幕截圖上的坐標數據  33      34      35     public ImageFindDemo(String keyImagePath) { 36         screenShotImage = this.getFullScreenShot(); 37         keyImage = this.getBfImageFromPath(keyImagePath); 38         screenShotImageRGBData = this.getImageGRB(screenShotImage); 39         keyImageRGBData = this.getImageGRB(keyImage); 40         scrShotImgWidth = screenShotImage.getWidth(); 41         scrShotImgHeight = screenShotImage.getHeight(); 42         keyImgWidth = keyImage.getWidth(); 43         keyImgHeight = keyImage.getHeight(); 44          45         //開始查找 46         this.findImage(); 47          48     } 49      50     /** 51      * 全屏截圖 52      * @return 返回BufferedImage 53      */ 54     public BufferedImage getFullScreenShot() { 55         BufferedImage bfImage = null; 56         int width = (int) Toolkit.getDefaultToolkit().getScreenSize().getWidth(); 57         int height = (int) Toolkit.getDefaultToolkit().getScreenSize().getHeight(); 58         try { 59             Robot robot = new Robot(); 60             bfImage = robot.createScreenCapture(new Rectangle(0, 0, width, height)); 61         } catch (AWTException e) { 62             e.PRintStackTrace(); 63         } 64         return bfImage; 65     } 66      67     /** 68      * 從本地文件讀取目標圖片 69      * @param keyImagePath - 圖片絕對路徑 70      * @return 本地圖片的BufferedImage對象 71      */ 72     public BufferedImage getBfImageFromPath(String keyImagePath) { 73         BufferedImage bfImage = null; 74         try { 75             bfImage = ImageIO.read(new File(keyImagePath)); 76         } catch (IOException e) { 77             e.printStackTrace(); 78         } 79         return bfImage; 80     } 81      82     /** 83      * 根據BufferedImage獲取圖片RGB數組 84      * @param bfImage 85      * @return 86      */ 87     public int[][] getImageGRB(BufferedImage bfImage) { 88         int width = bfImage.getWidth(); 89         int height = bfImage.getHeight(); 90         int[][] result = new int[height][width]; 91         for (int h = 0; h < height; h++) { 92             for (int w = 0; w < width; w++) { 93                 //使用getRGB(w, h)獲取該點的顏色值是ARGB,而在實際應用中使用的是RGB,所以需要將ARGB轉化成RGB,即bufImg.getRGB(w, h) & 0xFFFFFF。 94                 result[h][w] = bfImage.getRGB(w, h) & 0xFFFFFF; 95             } 96         } 97         return result; 98     } 99     100     101     /**102      * 查找圖片103      */104     public void findImage() {105         findImgData = new int[keyImgHeight][keyImgWidth][2];106         //遍歷屏幕截圖像素點數據107         for(int y=0; y<scrShotImgHeight-keyImgHeight; y++) {108             for(int x=0; x<scrShotImgWidth-keyImgWidth; x++) {109                 //根據目標圖的尺寸,得到目標圖四個角映射到屏幕截圖上的四個點,110                 //判斷截圖上對應的四個點與圖B的四個角像素點的值是否相同,111                 //如果相同就將屏幕截圖上映射范圍內的所有的點與目標圖的所有的點進行比較。112                 if((keyImageRGBData[0][0]^screenShotImageRGBData[y][x])==0113                         && (keyImageRGBData[0][keyImgWidth-1]^screenShotImageRGBData[y][x+keyImgWidth-1])==0114                         && (keyImageRGBData[keyImgHeight-1][keyImgWidth-1]^screenShotImageRGBData[y+keyImgHeight-1][x+keyImgWidth-1])==0115                         && (keyImageRGBData[keyImgHeight-1][0]^screenShotImageRGBData[y+keyImgHeight-1][x])==0) {116                     117                     boolean isFinded = isMatchAll(y, x);118                     //如果比較結果完全相同,則說明圖片找到,填充查找到的位置坐標數據到查找結果數組。119                     if(isFinded) {120                         for(int h=0; h<keyImgHeight; h++) {121                             for(int w=0; w<keyImgWidth; w++) {122                                 findImgData[h][w][0] = y+h; 123                                 findImgData[h][w][1] = x+w;124                             }125                         }126                         return;127                     }128                 }129             }130         }131     }132     133     /**134      * 判斷屏幕截圖上目標圖映射范圍內的全部點是否全部和小圖的點一一對應。135      * @param y - 與目標圖左上角像素點想匹配的屏幕截圖y坐標136      * @param x - 與目標圖左上角像素點想匹配的屏幕截圖x坐標137      * @return138      */139     public boolean isMatchAll(int y, int x) {140         int biggerY = 0;141         int biggerX = 0;142         int xor = 0;143         for(int smallerY=0; smallerY<keyImgHeight; smallerY++) {144             biggerY = y+smallerY;145             for(int smallerX=0; smallerX<keyImgWidth; smallerX++) {146                 biggerX = x+smallerX;147                 if(biggerY>=scrShotImgHeight || biggerX>=scrShotImgWidth) {148                     return false;149                 }150                 xor = keyImageRGBData[smallerY][smallerX]^screenShotImageRGBData[biggerY][biggerX];151                 if(xor!=0) {152                     return false;153                 }154             }155             biggerX = x;156         }157         return true;158     }159     160     /**161      * 輸出查找到的坐標數據162      */163     private void printFindData() {164         for(int y=0; y<keyImgHeight; y++) {165             for(int x=0; x<keyImgWidth; x++) {166                 System.out.print("("+this.findImgData[y][x][0]+", "+this.findImgData[y][x][1]+")");167             }168             System.out.println();169         }170     }171 172     173     public static void main(String[] args) {174         String keyImagePath = "D:/key.png";175         ImageFindDemo demo = new ImageFindDemo(keyImagePath);176         demo.printFindData();177     }178 179 }

  這種算法是精確比較,只要有一個像素點有差異,就會找不到圖片。當然,如果想指定一個比較的精確度,我也有個思路,就是在算法步驟4比較映射范圍內全部像素點的時候做個統計,如果90%的點都相同,那就是說精確度是0.9。

  另外,可能還要考慮效率問題,不過,我在我的應用場景中并不太在意效率。如果有朋友看到這篇文章,對這個話題有更好的想法,請留言。


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 上栗县| 绥德县| 泰来县| 高阳县| 五常市| 洪江市| 周宁县| 北票市| 礼泉县| 佛教| 会同县| 沙雅县| 云浮市| 姜堰市| 财经| 信丰县| 通许县| 太康县| 漳浦县| 邢台市| 渭南市| 苏州市| 中卫市| 武夷山市| 报价| 福州市| 安康市| 无极县| 永泰县| 嘉荫县| 泰安市| 郧西县| 葫芦岛市| 东阳市| 嫩江县| 宁晋县| 方正县| 淮北市| 崇左市| 青神县| 晴隆县|