C# 声明颜色时位图和OutOfMemory异常[8408,8337]

C# 声明颜色时位图和OutOfMemory异常[8408,8337],c#,arrays,memory,bitmap,C#,Arrays,Memory,Bitmap,基本上,我的程序是用最简单的嵌套循环逐像素搜索另一幅图像。 它可以在9x9图像中查找2x2,但无法在8408 x 8337分辨率下搜索(我想我不需要那么多,但我想检查它的速度有多慢) 声明彩色2D数组时出错 所以我请求帮助是因为为什么,以及如何解决这个问题 我怀疑OOM错误是由于SizeOfColorType*8337大于Int32。。。但我不确定这是否正确 using System; using System.Collections.Generic; using System.Linq; us

基本上,我的程序是用最简单的嵌套循环逐像素搜索另一幅图像。 它可以在9x9图像中查找2x2,但无法在8408 x 8337分辨率下搜索(我想我不需要那么多,但我想检查它的速度有多慢)

声明彩色2D数组时出错 所以我请求帮助是因为为什么,以及如何解决这个问题

我怀疑OOM错误是由于SizeOfColorType*8337大于Int32。。。但我不确定这是否正确

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;
        }

    }

}

使用系统;
使用System.Collections.Generic;
使用System.Linq;
使用系统文本;
使用System.Threading.Tasks;
使用系统图;
命名空间IMGReach
{
班级计划
{
静态void Main(字符串[]参数)
{
字符串basePath=@“C:\Users\Administrator\Desktop\IMGReachImages\1.jpg”;//8408x8337
字符串searchPath=@“C:\Users\Administrator\Desktop\IMGReachImages\2.jpg”;//69 x 56
位图b=新位图(基本路径);//基本图像
位图s=新位图(搜索路径);//要在基本图像内部搜索的图像
var x=图像图像(b,s);
Console.WriteLine(x[0]);//找到的映像的x坐标
Console.WriteLine(x[1]);//找到的映像的y坐标
控制台。写入(“结束”);
Console.ReadKey();
}
私有静态int[]ImageInImage(位图源,位图搜索)
{
//基于图像创建颜色数组
颜色[,]基本像素=区域阵列(源,0,0,source.Width,source.Height);
颜色[,]searchPixels=区域阵列(searchIt,0,0,searchIt.Width,searchIt.Height);
颜色hookPixel=searchPixels[0,0];
for(int xpos=0;xpos源宽度)
抛出新ArgumentException(“宽度参数大于源宽度”、“宽度”);
如果(高度>震源高度)
抛出新ArgumentException(“高度参数大于源高度”、“高度”);
颜色[,]像素集=新颜色[宽度,高度];//[2,2]
对于(int-ix=0;ix
8408 x 8337的图像包含7000多万像素。
Color
结构的大小至少为4个字节。因此,您尝试分配最小280兆字节。您的系统必须有280 MB的连续可用内存。如果您在32位系统上运行(或在32位模式下运行程序),很可能您没有可用的内存。因此,
OutOfMemoryException

情况变得更糟了。即使您设法为该图像分配内存,您的
ImageInImage
方法也需要分配大小相同的
basePixels
数组


到现在为止,您可能已经注意到,即使在小图像上,您的程序也非常慢。使用
GetPixel
读取图像颜色会非常慢。您需要研究如何使用,以便可以直接访问图像位。该MSDN主题有一个基本示例。如果您想有效地使用内部位图结构,您需要了解一些内部位图结构,但是如果您稍微搜索一下,有很多示例可用。

Hmm,但无论如何,我怀疑有一种方法可以做到这一点。。。但是如何管理这么大的内存量呢?@BartłomiejSobieszek将其存储在磁盘中,并对其进行部分查询