【问题标题】:How to create an array in a for loop如何在for循环中创建数组
【发布时间】:2010-11-07 21:26:07
【问题描述】:

好的,我需要像这样创建两个数组:

        double[][] TrainPatterns = { 
            new double[] { 0.0, 0.0 },
            new double[] { 0.0, 1.0 },
            new double[] { 0.0, 2.0 }
        };
        double[][] TrainResults = {
            new double[] { 0.0 },
            new double[] { 1.0 },
            new double[] { 1.0 }
        };

但每个都有 100 个项目。

我正在从图像中读取数组的值(TrainPatterns 包含像素的 x 和 y 坐标,TrainResults 包含像素的颜色,0 表示黑色,1 表示白色)。

我正在像这样遍历图像:

        Bitmap objBitmap = new Bitmap("im.bmp");
        for (int y = 0; y < objBitmap.Height; y++)
        {
            for (int x = 0; x < objBitmap.Width; x++)
            {
                // here I need to insert new double[] { (double)x, (double)y } to the
                // TrainPatterns array
                Color col = objBitmap.GetPixel(x, y);
                if (col.R == 255 && col.G == 255 && col.B == 255)
                {
                    // white color
                    // here I need to insert new double[] { 1.0 } to the
                    // TrainResults 
                }
                if (col.R == 0 && col.G == 0 && col.B == 0)
                {
                    // black color
                    // here I need to insert new double[] { 0.0 } to the
                    // TrainResults 
                }
            }
        }

如何在 for 循环中动态地将项目添加到这些数组中?我知道图像的宽度为 10px,高度为 10px,所以我知道数组的长度都是 100。

【问题讨论】:

  • 我只需要问一些愚蠢的问题。 1)为什么要存储每个坐标?由于数组是密集的,你当然可以只保存这些值,它们的位置决定了坐标。 2) 为什么将每个结果存储为单个元素double[]?你不能只使用double 吗? 3) 你可以使用位图本身作为数据结构,使用 GetPixel 和 SetPixel 作为访问器吗? 4) 或者,您能否将整个位图存储为两个长整数(空间足以容纳 128 位)?

标签: c#


【解决方案1】:

您肯定想在开始循环之前分配数组,完成后您会想要使用结果。当像素不是白色或黑色时,你应该做一些有意义的事情。像这样的:

        Bitmap objBitmap = new Bitmap("im.bmp");
        double[][] array = new double[objBitmap.Height][];
        for (int y = 0; y < objBitmap.Height; y++) {
            array[y] = new double[objBitmap.Width];
            for (int x = 0; x < objBitmap.Width; x++) {
                Color col = objBitmap.GetPixel(x, y);
                if (col == Color.White) array[y][x] = 1.0;
                else if (col == Color.Black) array[y][x] = 0.0;
                else array[y][x] = 0.5;  // whatever
            }
        }
        // Do something with array
        //...

不确定位图的生命周期,您应该在某处调用 objBitmap.Dispose()。利用 using 语句。

【讨论】:

    【解决方案2】:

    就在您的 for (int x = 0; x &lt; objBitmap.Width; x++) 创建您的双精度数组并在上述循环中插入该数组之前。然后在循环之后将其插入您在任何循环之前实例化的TrainPatterns

    【讨论】:

    • 你想让我教你如何实例化一个双精度数组?
    • 不怎么样。在哪里。 “在此之前执行此操作”不像代码示例那么清晰。
    【解决方案3】:

    使用List&lt;double&gt; 而不是double[]。它们在创建后可以改变大小,而数组则不能。

    var trainResults = new List<double[]>();
    
    for(int y = 0; ...)
    {
        for(int x = 0; ...)
        {
            if(colors match...)
            {
                trainResults.Add(new double[] { x, y });
            }
            // etc...
        }
    }
    

    另外,我建议你创建一个新结构,而不是双数组,这样当你使用这些结果时,你的代码在做什么会更明显:

    class TrainResult
    {
        TrainResult(int x = 0; int y = 0)
        {
            this.X = x;
            this.Y = y;
        }
    
        public int X;
        public int Y;
    }
    
    // ...
    
    for(int y = 0; ...)
        for(int x = 0; ...)
            if(match ...)
                trainResults.Add(new TrainResult(x, y));
    
    // ...
    
    foreach(TrainResult result in trainResults)
    {
        // Do something with result.X, result.Y.
        // This is more obvious than result[0], result[1]
    }
    

    【讨论】:

      【解决方案4】:

      看起来你想做的事情可以使用 LINQ 而不是for 循环轻松完成:

      Bitmap objBitmap = new Bitmap("im.bmp");
      var TrainPattern = (from y in Enumerable.Range(0, objBitmap.Height)
                          from x in Enumerable.Range(0, objBitmap.Width)
                          select new double[] { x, y }).ToArray();
      var TrainResults = (from y in Enumerable.Range(0, objBitmap.Height)
                          from x in Enumerable.Range(0, objBitmap.Width)
                          let col = objBitmap.GetPixel(x, y)
                          select (col.R == 255 && col.G == 255 && col.B == 255) ?
                                  new[] { 1.0 } : new[] { 0.0 }).ToArray();
      

      请注意,这假设每个像素都是黑色或白色。

      【讨论】:

        【解决方案5】:

        除非您的数据结构有特殊要求,否则我强烈建议将这些位存储在BitArray

        Bitmap objBitmap = new Bitmap("im.bmp");
        var white = new BitArray(objBitmap.Width*objBitmap.Height);
        var black = new BitArray(objBitmap.Width*objBitmap.Height);
        for (int y = 0, i = 0; y < objBitmap.Height; ++y)
        {
            for (int x = 0; x < objBitmap.Width; ++x, ++i)
            {
                Color c = objBitmap.GetPixel(x, y);
                white[i] = c.R == 255 && c.G == 255 && c.B == 255;
                black[i] = c.R == 0 && c.G == 0 && c.B == 0;
            }
        }
        

        我不知道您喜欢如何处理既不是黑色也不是白色的颜色,因此上面的代码计算了两个位图,一个用于纯白色,另一个用于纯黑色。如果您想要中间位,可以使用var middle = black[i].Clone().Not().And(white.Clone().Not())(我认为;我从未使用过这些方法)。

        从这些位图中访问位非常简单:

        if (white[x + objBitmap.Width*y]) { /* The pixel at (x, y) is white. */ }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2017-05-06
          • 1970-01-01
          • 1970-01-01
          • 2022-08-11
          • 2014-10-25
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多