لقد قمت بكتابة بعض مساعدي الألعاب باستخدام معالج الأزرار من قبل. هناك وظيفة تسمى FindPic، والتي تبحث عن صورة معينة ضمن نطاق الشاشة وترجع موضع الإحداثيات الذي تم العثور عليه.
الآن، تنفذ Java وظيفة مشابهة لهذه الوظيفة.
وصف الخوارزمية:
التقط لقطة شاشة واحصل على الصورة أ (الصورة المستهدفة التي تبحث عنها هي الصورة ب)؛
اجتياز بكسلات الصورة A، ووفقًا لحجم الصورة B، احصل على الزوايا الأربع للصورة B المعينة للنقاط الأربع في الصورة A؛
تتم مقارنة النقاط الأربع التي تم الحصول عليها مع قيم بكسلات الزاوية الأربعة في الشكل ب. إذا كانت النقاط الأربع هي نفسها، فانتقل إلى الخطوة 4، وإلا فارجع إلى الخطوة 2 للمتابعة؛
لمزيد من المقارنة، قارن جميع النقاط ضمن نطاق التعيين مع جميع النقاط في الشكل B. إذا كانت جميعها متماثلة، فقد تم العثور على الصورة، وإلا فارجع إلى الخطوة 2 للمتابعة؛
هنا تتم المقارنة بين وحدات البكسل عن طريق الحصول على قيمة RGB لكل بكسل من خلال كائن BufferedImage. كما يلي، قم بتحويل BufferedImage إلى مصفوفة ثنائية الأبعاد:
/** * احصل على مصفوفة RGB للصورة بناءً على BufferedImage * @param bfImage * @return */ public static int[][] getImageGRB(BufferedImage bfImage) { int width = bfImage.getWidth(); ); int[][] result = new int[height][width]; = 0; h < height; h++) { for (int w = 0; w < width; w++) { // استخدم getRGB(w, h) للحصول على قيمة لون النقطة، وهي ARGB، ولكن في التطبيقات الفعلية ، إنه RGB، لذا يجب تحويل ARGB إلى RGB، أي bufImg.getRGB(w, h) & 0xFFFFFF. result[h][w] = bfImage.getRGB(w, h) & 0xFFFFFF;
تتم مقارنة ما إذا كانت قيم RGB للبكسلتين متماثلة من خلال عملية XOR (والتي يُقال إنها أكثر كفاءة من ==). إذا كانت القيمة التي تم الحصول عليها بعد عملية XOR هي 0، فهذا يعني أن قيم RGB البكسلان متماثلان، وإلا فليسا متماثلين.
كود جافا الكامل للخوارزمية مرفق أدناه:
package com.jebysun.test.imagefind; import java.awt.AWTException; import java.awt.Rectangle; import java.awt.Toolkit; import java.awt.image.BufferedImage; .File; import java.io.IOException; import javax.imageio.ImageIO; Jeby Sun * @date 2014-09-13 * @website http://www.jebysun.com */ public class ImageFindDemo { BufferedImage screenShotImage; //Screenshot BufferedImage keyImage; // ابحث عن الصورة المستهدفة int scrShotImgWidth; int scrShotImgHeight; // ارتفاع لقطة الشاشة int keyImgWidth; keyImgHeight; // ابحث عن ارتفاع الصورة المستهدفة int[][] screenShotImageRGBData; // بيانات لقطة الشاشة RGB int[][] keyImageRGBData; // ابحث عن بيانات RGB للصورة المستهدفة int[][][] findImgData; target البيانات الإحداثية للأيقونة الموجودة في لقطة الشاشة public ImageFindDemo(String keyImagePath) { screenShotImage = this.getFullScreenShot(); = this.getBfImageFromPath(keyImagePath); screenShotImageRGBData = this.getImageGRB(screenShotImage); keyImageRGBData = this.getImageGRB(keyImage); keyImgWidth = keyImage.getWidth(); keyImgHeight = keyImage.getHeight(); // ابدأ في البحث عن this.findImage(); } /** * لقطة شاشة بملء الشاشة* @return Return BufferedImage */ public BufferedImage getFullScreenShot() { BufferedImage bfImage = عرض فارغ = (كثافة العمليات) Toolkit.getDefaultToolkit().getScreenSize().getWidth(); int height = (int) Toolkit.getDefaultToolkit().getScreenSize().getHeight(); محاولة { Robot robot = new Robot(); مستطيل جديد (0، 0، العرض، الارتفاع) } قبض (AWTException e) { e.printStackTrace(); } return bfImage; } /** * اقرأ الصورة المستهدفة من الملف المحلي * @param keyImagePath - المسار المطلق للصورة * @return كائن BufferedImage للصورة المحلية */ public BufferedImage getBfImageFromPath (String keyImagePath) { BufferedImage bfImage = null; حاول { bfImage = ImageIO.read(new File(keyImagePath)); } Catch (IOException e) { e.printStackTrace() } return bfImage } /** * احصل على مصفوفة RGB للصورة بناءً على BufferedImage * @param bfImage * @return */ public int[][] ] getImageGRB (BufferedImage bfImage) { int width = bfImage.getWidth(); height = bfImage.getHeight(); int[][] result = new int[height][width]; for (int h = 0; h < height; h++) { for (int w = 0; w < width; w++ ) {// استخدم getRGB(w, ح) قيمة اللون التي تم الحصول عليها في هذه المرحلة هي ARGB، ولكن في التطبيقات الفعلية يتم استخدام RGB، لذلك يجب تحويل ARGB إلى RGB، أي bufImg.getRGB(w, h) & 0xFFFFFF. result[h][w] = bfImage.getRGB(w, h) & 0xFFFFFF; 2] // اجتياز بيانات بكسل لقطة الشاشة for(int y=0; y<scrShotImgHeight-keyImgHeight; y++) { for(int x=0; هل قيم النقاط الأربع والبكسلات الأربعة في الشكل B هي نفسها؟ // إذا كانت متماثلة، قارن جميع النقاط داخل نطاق التعيين في لقطة الشاشة مع جميع النقاط في الصورة المستهدفة. 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) { boolean isFinded = isMatchAll(y, x); // إذا كانت نتائج المقارنة متماثلة تمامًا، فهذا يعني أنه تم العثور على الصورة، ويتم ملء بيانات إحداثيات الموضع التي تم العثور عليها في مصفوفة نتائج البحث. if(isFinded) { for(int h=0; h<keyImgHeight; h++) { for(int w=0; w<keyImgWidth; w++) { findImgData[h][w][0] = y+h findImgData[; h][w][1] = x+w } } return; حدد ما إذا كانت جميع النقاط الموجودة ضمن نطاق تعيين الصورة المستهدفة على لقطة الشاشة تتوافق مع نقاط الصورة الصغيرة واحدة لواحدة. * @param y - الإحداثي y للقطة الشاشة التي تريد مطابقة نقطة البكسل في الزاوية اليسرى العليا من الصورة المستهدفة * @param x - الإحداثي x للقطة الشاشة التي تريد مطابقة نقطة البكسل في الزاوية اليسرى العليا للصورة المستهدفة * @return */ public boolean isMatchAll(int y, int x) { int bigY = 0; int xor = 0; for(int أصغرY=0; أصغرY<keyImgHeight; أصغرY++) { bigY = y+smallerY; for(int أصغر X=0; أصغر X<keyImgWidth; أصغر X++) { bigX = x+smallerX; ]^screenShotImageRGBData[biggerY][biggerX]; if(xor!=0) { return false; } bigX = x } return true } /** * إخراج البيانات الإحداثية التي تم العثور عليها*/ public 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(keyImagePath);demo.printFindData();
هذه الخوارزمية عبارة عن مقارنة دقيقة، وطالما كان هناك اختلاف في بكسل واحد، فلن يتم العثور على الصورة. بالطبع، إذا كنت تريد تحديد دقة المقارنة، فلدي أيضًا فكرة، وهي إجراء إحصائيات عند مقارنة جميع وحدات البكسل ضمن نطاق التعيين في الخطوة 4 من الخوارزمية، إذا كانت 90٪ من النقاط متماثلة، فهذا يعني الدقة 0.9.
بالإضافة إلى ذلك، يمكن أيضًا أخذ مشكلات الكفاءة في الاعتبار، لكنني لا أهتم كثيرًا بالكفاءة في سيناريو التطبيق الخاص بي. إذا قرأ أي صديق هذا المقال ولديه أفكار أفضل حول هذا الموضوع، يرجى ترك رسالة.