2012-12-01 24 views
10

Tôi đang cố gắng xây dựng một ứng dụng giải quyết một câu đố (cố gắng phát triển một thuật toán đồ thị), và tôi không muốn nhập thông tin nhập mẫu bằng tay mọi lúc.Tìm hình ảnh bên trong một hình ảnh khác

Chỉnh sửa: Tôi không cố xây dựng trò chơi. Tôi đang cố gắng xây dựng một đại lý chơi trò chơi "SpellSeeker"

Giả sử tôi có hình ảnh (xem tệp đính kèm) trên màn hình với số trong đó và tôi biết vị trí của các hộp và tôi có chính xác hình ảnh cho những con số này. Những gì tôi muốn làm là chỉ cần cho biết hình ảnh (số) là trên hộp tương ứng.

Numbers http://i46.tinypic.com/3089vyt.jpg

Vì vậy, tôi đoán tôi cần phải thực hiện

bool isImageInsideImage(Bitmap numberImage,Bitmap Portion_Of_ScreenCap) hoặc một cái gì đó như thế.

Những gì tôi đã cố gắng là (sử dụng thư viện AForge)

public static bool Contains(this Bitmap template, Bitmap bmp) 
{ 
    const Int32 divisor = 4; 
    const Int32 epsilon = 10; 

    ExhaustiveTemplateMatching etm = new ExhaustiveTemplateMatching(0.9f); 

    TemplateMatch[] tm = etm.ProcessImage(
     new ResizeNearestNeighbor(template.Width/divisor, template.Height/divisor).Apply(template), 
     new ResizeNearestNeighbor(bmp.Width/divisor, bmp.Height/divisor).Apply(bmp) 
     ); 

    if (tm.Length == 1) 
    { 
     Rectangle tempRect = tm[0].Rectangle; 

     if (Math.Abs(bmp.Width/divisor - tempRect.Width) < epsilon 
      && 
      Math.Abs(bmp.Height/divisor - tempRect.Height) < epsilon) 
     { 
      return true; 
     } 
    } 

    return false; 
} 

Nhưng nó trả về false khi tìm kiếm một dấu chấm đen trong hình ảnh này.

Làm cách nào để triển khai tính năng này?

+0

Một số trò chơi sudoku hoặc tic tac toe? – bonCodigo

+0

Bạn có thấy các câu hỏi khác trên [mặt bằng tương tự] không (http://stackoverflow.com/questions/2472467/how-to-find-one-image-inside-of-another)? – bonCodigo

+0

Đó là trò chơi có tên "spellseeker". Nhưng điều quan trọng là tôi chỉ muốn xây dựng algorihm để giải quyết một vấn đề như vậy. Và có, thực sự tôi tìm thấy giải pháp này trong các câu hỏi khác, nhưng họ đã không giúp tôi. Và tha thứ cho tôi vì sự lười biếng của tôi nhưng tôi thực sự nghĩ rằng phải có một cách dễ dàng hơn cho việc này :) – marvin

Trả lời

5

tôi trả lời câu hỏi của tôi kể từ khi tôi đã tìm thấy các giải pháp:

this làm việc ra cho tôi:

System.Drawing.Bitmap sourceImage = (Bitmap)Bitmap.FromFile(@"C:\SavedBMPs\1.jpg"); 
      System.Drawing.Bitmap template = (Bitmap)Bitmap.FromFile(@"C:\SavedBMPs\2.jpg"); 
      // create template matching algorithm's instance 
      // (set similarity threshold to 92.5%) 

      ExhaustiveTemplateMatching tm = new ExhaustiveTemplateMatching(0.921f); 
       // find all matchings with specified above similarity 

       TemplateMatch[] matchings = tm.ProcessImage(sourceImage, template); 
       // highlight found matchings 

      BitmapData data = sourceImage.LockBits(
       new Rectangle(0, 0, sourceImage.Width, sourceImage.Height), 
       ImageLockMode.ReadWrite, sourceImage.PixelFormat); 
      foreach (TemplateMatch m in matchings) 
      { 

        Drawing.Rectangle(data, m.Rectangle, Color.White); 

       MessageBox.Show(m.Rectangle.Location.ToString()); 
       // do something else with matching 
      } 
      sourceImage.UnlockBits(data); 

vấn đề duy nhất là nó đã tìm thấy tất cả (58) hộp cho trò chơi đã nói. Nhưng thay đổi giá trị 0,921f thành 0,98 khiến nó hoàn hảo, tức là nó chỉ tìm thấy hình ảnh của số được chỉ định (mẫu)

Chỉnh sửa: Tôi thực sự phải nhập các ngưỡng tương tự khác nhau cho các hình ảnh khác nhau.Tôi đã tìm thấy các giá trị được tối ưu hóa bằng cách thử, cuối cùng tôi có một chức năng như

float getSimilarityThreshold(int number) 
1

Một cách tiếp cận tốt hơn là xây dựng một lớp tùy chỉnh chứa tất cả thông tin bạn cần thay vì dựa vào chính hình ảnh đó.

Ví dụ:

public class MyTile 
{ 
    public Bitmap TileBitmap; 
    public Location CurrentPosition; 
    public int Value; 
} 

Bằng cách này bạn có thể "di chuyển xung quanh" lớp ngói và đọc giá trị từ các lĩnh vực Value thay vì phân tích hình ảnh. Bạn chỉ cần vẽ bất kỳ hình ảnh nào mà lớp giữ ở vị trí mà nó đang giữ.

Bạn gạch có thể được tổ chức trong một mảng như:

private list<MyTile> MyTiles = new list<MyTile>(); 

Mở rộng lớp khi cần thiết (và nhớ để Vứt bỏ những hình ảnh khi họ không còn cần thiết).

nếu bạn thực sự muốn xem nếu có một hình ảnh bên trong hình ảnh, bạn có thể kiểm tra phần mở rộng này tôi đã viết cho bài khác (mặc dù trong mã VB):
Vb.Net Check If Image Existing In Another Image

+0

Cảm ơn câu trả lời này. Tôi đã có một lớp học tương tự như thế này. Tôi có một lớp Node với các giá trị (trong các hộp văn bản), và một lớp Tile có một mảng Node. Nhưng vấn đề khởi tạo tất cả các nút vẫn còn. Tôi có thể nhập chúng vào hộp văn bản nhưng nó vẫn có nghĩa là tôi phải nhập ~ 60 số bằng tay, trong thời gian 2 giây. Vì vậy, tôi đang tìm cách khởi tạo chúng bằng cách sử dụng hình ảnh màn hình. – marvin