2014-10-11 62 views
0

基本上,它是我的程序,它使用最简单的嵌套循环逐个像素地搜索另一图像中的图像。 它可以在9x9图像中查找2x2,但它无法在8408 x 8337分辨率中搜索(我想我不需要那么多,但我想检查它会有多慢)声明颜色[8408,8337]时出现位图和OutOfMemory异常

发生错误时声明颜色2D阵列 所以我寻求帮助,因为为什么,以及如何解决这个问题

我怀疑OOM错误是由于他SizeOfColorType * 8337大于Int32 ...但我不知道如果这是正确的

enter image description here

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Threading.Tasks; 

using System.Drawing; 

namespace IMGReach 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 

      String basePath = @"C:\Users\Administrator\Desktop\IMGReachImages\1.jpg";  // 8408x8337 
      String searchPath = @"C:\Users\Administrator\Desktop\IMGReachImages\2.jpg";  // 69 x 56 

      Bitmap b = new Bitmap(basePath);  // base image 
      Bitmap s = new Bitmap(searchPath);  // image to search inside of base image 

      var x = ImageInImage(b, s); 
      Console.WriteLine(x[0]); // x coord of found image 
      Console.WriteLine(x[1]); // y coord of found image 
      Console.Write("END"); 
      Console.ReadKey(); 
     } 

     private static int[] ImageInImage(Bitmap source, Bitmap searchIt) 
     { 
      // Creates array of colors based on image 
      Color[,] basePixels = AreaToArray(source, 0, 0, source.Width, source.Height); 
      Color[,] searchPixels = AreaToArray(searchIt, 0, 0, searchIt.Width, searchIt.Height); 

      Color hookPixel = searchPixels[0, 0]; 

      for (int xpos = 0; xpos < basePixels.GetLength(0); xpos++) 
      { 
       for (int ypos = 0; ypos < basePixels.GetLength(1); ypos++) 
       { 
        if (basePixels[xpos, ypos] == hookPixel) 
        { 
         Color[,] checkMap = AreaToArray(source, xpos, ypos, searchIt.Width, searchIt.Height); 
         if (sameArray(checkMap, searchPixels)) 
          return new int[] { xpos, ypos }; 
        } 
       } 
      } 

      return null; 
     } 

     private static Color[,] AreaToArray(Bitmap source, int start_x, int start_y, int width, int height) 
     { 
      if (start_x < 0) 
       throw new ArgumentException("Invalid parameter value (less than zero)", "start_x"); 

      if (start_y < 0) 
       throw new ArgumentException("Invalid parameter value (less than zero)", "start_y"); 

      if (width > source.Width) 
       throw new ArgumentException("Width parameter is bigger than source width", "width"); 

      if (height > source.Height) 
       throw new ArgumentException("Height parameter is bigger than source height", "height"); 

      Color[,] pixelSet = new Color[width, height]; // [2,2] 

      for (int ix = 0; ix < width; ix++) 
       for (int iy = 0; iy < height; iy++) 
        pixelSet[ix, iy] = source.GetPixel(ix + start_x, iy + start_y); 

      return pixelSet; 
     } 

     private static bool sameArray(int[,] a1, int[,] a2) 
     { 

      if (a1.GetLength(0) != a2.GetLength(0)) 
       return false; 

      if (a1.GetLength(1) != a2.GetLength(1)) 
       return false; 

      for (int i = 0; i < a1.GetLength(0); i++) 
      { 
       for (int j = 0; j < a1.GetLength(1); j++) 
       { 
        if (a1[i, j] == a2[i, j]) 
        { 
         continue; 

        } 
        else 
        { 
         return false; 
        } 
       } 
      } 

      return true; 
     } 

     private static bool sameArray(Color[,] a1, Color[,] a2) 
     { 
      if (a1.GetLength(0) != a2.GetLength(0)) 
       return false; 

      if (a1.GetLength(1) != a2.GetLength(1)) 
       return false; 

      for (int i = 0; i < a1.GetLength(0); i++) 
      { 
       for (int j = 0; j < a1.GetLength(1); j++) 
       { 
        if (a1[i, j] == a2[i, j]) 
        { 
         continue; 
        } 
        else 
        { 
         return false; 
        } 
       } 
      } 

      return true; 
     } 

    } 

} 

回答

2

8408 x 8337包含一个超过7000万像素的图像。 Color结构的大小至少为4个字节。所以你试图分配至少280兆字节。您的系统必须有280兆字节的连续内存空闲。如果您在32位系统上运行(或以32位模式运行程序),则很有可能您没有可用的内存。因此,OutOfMemoryException

它变得更糟。即使您设法为该映像分配内存,您的ImageInImage方法也需要分配basePixels阵列,该阵列的大小相同。

您现在可能已经注意到,即使在小图片上,您的程序也很慢。使用GetPixel来读取图像颜色将会非常慢。您需要查看使用Bitmap.LockBits,以便您可以直接访问图像位。该MSDN主题有一个基本示例。如果你想有效地使用它,你需要了解一些关于内部位图结构的知识,但是如果你搜索一下,有很多例子可用。

+0

嗯,但无论如何,我怀疑有一种方法可以做到这一点......但如何管理如此大量的内存? – 2014-10-11 04:13:54

+1

@BartłomiejSobieszek将它放在磁盘中,并在零件中进行查询。 – Mephy 2014-10-11 04:16:28

+0

会分裂这个图像(让我们说)100二维颜色阵列可以更好地工作?我相信GC可以释放unsdes数组的程序,因为我不能在Color数组上使用Dispose()。 @Up这是我的第一个想法,thx确认:) – 2014-10-11 04:16:43

相关问题