【问题标题】:difficulty writing a multilevel for loop难以编写多级 for 循环
【发布时间】:2017-11-04 23:07:07
【问题描述】:

我有一个单一的暗淡数组,其中存储了图像的像素。我正在尝试将它作为二维数组打印到文件中。

每张图片为28*28像素,数组包含60000个。

我对输出单个图像的数学没有问题:

void makeImage(const std::string& filename,const char * insertion, const unsigned int& width, const unsigned int & height)
{
    int i = 0;
    FILE *fp = fopen(filename.c_str(), "wb"); /* b - binary mode */
    (void)fprintf(fp, "P6\n%d %d\n255\n", width, height);
    for (int x = 0; x < width; ++x)
    {
        for (int y = 0; y < height; ++y)
        {
            static unsigned char color[3];
            color[0] = *(insertion + i);  /* red */
            color[1] = *(insertion + i);  /* green */
            color[2] = *(insertion + i);  /* blue */
            (void)fwrite(color, 1, 3, fp);
            i++;
        }
    }
    (void)fclose(fp);
}

所以如果我在哪里做:

makeimage("myfile.ppm",&myarray[0],28,28); //First image.
makeimage("myfile2.ppm",&myarray[785],28,28); //Second image. ext.

但我想获得一张包含所有 60000 个图像的图像。作为 6860x6860 像素的图像。

但要做到这一点的数学让我很头疼。

【问题讨论】:

  • 请注意,6860*6860 = 47,059,600 不等于 28*28*60,000 = 47,040,000,这基本上意味着您不能完全适合所有图像,因为 6,860 / 28 = 245245*245 = 60,025 还有 25 个图像。
  • 您想如何将这 60,000 张图像排列成一个大马赛克?由于您正在逐列序列化这些图像,因此您已经将它们作为一张图像,高 28 像素,宽 1,680,000 像素。
  • 您需要使用另一个网格,例如 100 x 600 的图像,即:2800 x 16800 像素。
  • 顺便说一句,C 代码标记为 C++。为什么会这样?
  • OT:在 C++ 中使用 iostream。

标签: c++ arrays for-loop


【解决方案1】:

您无法将这些图像完全放入一个 60000 个图像正方形中,但您可以使用例如 600 行和 100 列的网格。 (生成的图像将为 16800 x 2800。)

我确信你可以处理 C++ 实现,所以这里是数学:

你有一个图像数组:

|----im1----||----im2----|....|----im60000----|

你想得到一个合成图像:

|----im1----||----im2----|..|----im600----|

|---im601---||---im602---|....|---im1200----|

...

|--im59401--||--im59402--|....|--im60000--|

这里有一些伪代码可以做到这一点。

for a in 600
  for b in 28
    for c in 100
      for d in 28
        result[100*28*(28*a + b) + 28*c + d] = arr[28*28*(100*a + c) + 28*b + d]

这里,result 是你的大输出图像,arr 是你的大输入数组。

基本上,第一个和第三个循环处理图像的位置,第二个和第四个循环处理当前图像中当前像素的位置。

它不是很漂亮,但它确实有效。 我想你必须考虑颜色,但我假设你正在解析 MNIST 数据(60000 个 28x28 手写数字图像),我相信它是灰度的。

祝你的项目好运。

【讨论】:

  • 你的想法是对的,但是使用 fwrite 有点困难,因为我是逐个像素地写的。或将其输出到另一个单一的暗淡阵列。我可以批量复制到文件中。
  • 好的,我为你更新了答案。一般来说,将二维数组折叠成一维数组非常简单:将arr[a][b] 更改为arr[a*b_max + b]
  • 似乎这超出了数组的范围。 wandbox.org/permlink/M30rarWX42HaId2x
  • 您的代码会导致段错误,因为您尝试为长度为 47040000 的数组分配内存。我认为您无法按照您的想法执行此操作。尝试将图像存储在一个文件中,并逐个像素地操作该图像,而不是尝试将整个数组加载到 RAM 中。
  • 魔杖盒上的数组只是一个例子,我已经有一个包含有效数据的数组。
【解决方案2】:

由于您要输出 6860 行 6860 点,并且您访问文件的方式是顺序的,因此首先确定单行的形成方式:

  1. 在一条线上,有 6860 个点或列。
  2. 第一行的前 28 个点来自第一张图像,接下来的 28 个来自第二张图像,依此类推。
  3. 第 29 行的前 28 个点来自第 246 个图像,依此类推。

用 c/c++ 粗略表述一下:

int image_index = (y / 28 * 245) + (x / 245);
int source_y = y % 28;
int source_x = x % 28;
int source_index = image_index * 28 * 28 + source_y * 28 + source_x;

【讨论】:

  • 6860 x 6860 是不可能的。图片不完全适合。
  • 6860 x 6860 是绝对可能的,因为图像适合。确实,生成的图像中会有一些剩余空间,但由于问题中提到了尺寸,我想提问方希望这样。如何排列子图像的问题已经在其他 cmet 中讨论过。
  • 我的观点是,你无法用 60,000 张 28x28 像素的图像来制作一个正方形。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-01-26
  • 2015-12-09
  • 2013-02-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多