超出最大允许尺寸

2024-05-17 06:34:41 发布

您现在位置:Python中文网/ 问答频道 /正文

我正试图用π和地球在海平面上的引力常数转换成双星来绘制一幅基于宇宙质量的画。我已经做了数学,我有正确的尺寸,它应该只有不到1兆内存,但我运行到最大允许尺寸超过值错误。你知道吗

代码如下:

import matplotlib.pyplot as plt
import matplotlib.cm as cm
import numpy as np

boshi = 123456789098765432135790864234579086542098765432135321 # universal mass

genesis = boshi ** 31467 # padding

artifice = np.binary_repr(genesis) # formatting

A = int(artifice) 

D = np.array(A).reshape(A, (1348, 4117))

plt.imsave('hello_world.png', D, cmap=cm.gray) # save image

我一直在D = np.array...遇到错误,也许我的整形太大了,但它只比4k大一点。似乎这对gpu增强的colab应该没有问题。在我的家用电脑上也不能运行同样的错误。这个问题会用更多的内存来解决吗?你知道吗


Tags: 内存importgenesis地球matplotlib尺寸as错误
2条回答

使其工作

问题是artifice = np.binary_repr(genesis)创建了一个字符串。字符串由1348 * 4117 = 5549716个数字组成,所有数字都是0和1。如果将字符串转换为python整数A = int(artifice),您将(a)等待很长时间,并且(B)得到一个不可iterable对象。用np.array(A)创建的数组将只有一个元素。你知道吗

好消息是,您可以完全绕过耗时的步骤,因为字符串artifice已经是一个iterable:

D = np.array(list(artifice), dtype=np.uint8).reshape(1348, 4117)

步骤list(artifice)将需要几秒钟,因为它必须拆分字符串,但其他一切都应该非常快。你知道吗

使用plt.imsave('hello_world.png', D, cmap=cm.gray)可以轻松绘制:

enter image description here

颜色映射

保存图像时,您可以轻松地将颜色映射更改为coolwarm或任何您想要的颜色。请记住,您的图像是二进制的,因此实际上只有两个值很重要:

plt.imsave('hello_world2.png', D, cmap=cm.coolwarm)

enter image description here

探索

你有机会在这里给你的形象添加丰富的色彩。通常,PNG是8位的。例如,不必将genesis转换为位,您可以从中提取字节来构造图像。您还可以使用半字节(半字节)来构造一个16色的索引图像。通过一点填充,您甚至可以确保您有三个数据点的倍数,并以任何方式创建一个全色RGB图像。我将不讨论更复杂的选项,但我想探讨如何从字节中生成一个简单的图像。你知道吗

5549716位是693715 = 5 * 11 * 12613字节(有四个前导零位)。这是一个非常糟糕的分解,导致图像大小为55x12613,所以让我们去掉上面的半字节:虽然693716的分解和693715的分解一样糟糕,但是693714的因子很好地融入了597 * 1162。你知道吗

您可以使用自己的^{}方法将整数转换为字节数组:

from math import ceil

byte_genesis = genesis.to_bytes(ceil(genesis.bit_length() / 8), 'big')

我之所以使用内置的^{}而不是^{},是因为它返回整数而不是浮点。你知道吗

转换大整数的速度非常快,因为bytes对象可以直接访问整数的数据:即使它复制了一个副本,实际上也不进行任何处理。它甚至可以共享缓冲区,因为bytesint在名义上是不可变的。类似地,您可以使用^{}bytes创建一个numpy数组,作为同一内存位置的视图:

img = np.frombuffer(byte_genesis, dtype=np.uint8)[1:].reshape(597, 1162)

因为bytes_genesis必须足够大以容纳整个genesis,所以[1:]对于切掉前导的半字节是必要的。您还可以在bytes侧切掉:

img = np.frombuffer(byte_genesis[1:], dtype=np.uint8).reshape(597, 1162)

结果是一致的。下面是图片的样子:

plt.imsave('hello_world3.png', img, cmap=cm.viridis)

结果太大,无法上载(因为它不是二进制图像),但下面是随机选择的示例:

enter image description here

我不确定这是否是美学上你正在寻找的,但希望这能为你提供一个开始研究如何将非常大的数字转换成数据缓冲区的地方。你知道吗

更多选项,因为这很有趣

我想看看在这里使用半字节而不是字节,因为这样可以使每个像素有16种颜色,像素是原来的两倍。您可以从以下位置获得1162x1194图像

temp = np.frombuffer(byte_genesis, dtype=np.uint8)[1:]

这里有一种方法可以解包小字节:

img = np.empty((1162, 1194), dtype=np.uint8)
img.ravel()[::2] = np.bitwise_and(temp >> 4, 0x0F)
img.ravel()[1::2] = np.bitwise_and(temp, 0x0F)

使用jet这样的颜色映射,您可以得到:

plt.imsave('hello_world4.png', img, cmap=cm.jet)

enter image description here

另一个选择(从某种意义上说是相反的方向)是根本不使用颜色贴图。相反,您可以将您的空间除以三的因子,并在RGB空间中生成您自己的颜色。幸运的是,693714的主要因素之一是3。因此,您可以拥有一个398x581图像(693714 == 3 * 398 * 581)。你如何解释这些数据比平时更取决于你。你知道吗

在我继续之前请注意

使用黑白二值图像,您可以控制图像的颜色、大小和方向。使用8位数据,您可以控制位的采样方式(8位或更少,如4位示例中所示)、解释的端点、颜色映射和图像大小。使用全色,可以将每个三元组视为单独的颜色,将整个数据集视为三个连续的颜色平面,甚至可以对数组应用Bayer filter之类的操作。除了尺寸、顺序、每个样本的位数等其他选项之外

下面将显示颜色三元组和三个颜色平面选项。你知道吗

全彩图像

要将每组3个连续字节视为RGB三元组,可以执行以下操作:

img = temp.reshape(398, 581, 3)
plt.imsave('hello_world5.png', img)

请注意,在这种情况下没有颜色映射。你知道吗

enter image description here

将数据解释为三个颜色平面需要额外的步骤,因为^{}期望最后一个维度的大小为3。^{}是一个很好的工具:

img = np.rollaxis(temp.reshape(3, 398, 581), 0, 3)
plt.imsave('hello_world6.png', img)

enter image description here

我无法重现你的问题,因为这行A = int(artifice)花了很长时间。我用一个,for循环来替换它,使每个数字都能自己转换。代码工作,然后产生所需的图像。你知道吗

import matplotlib.pyplot as plt
import matplotlib.cm as cm
import numpy as np

boshi = 123456789098765432135790864234579086542098765432135321
genesis = boshi ** 31467
artifice = np.binary_repr(genesis)

D = np.zeros((1348, 4117), dtype=int)
for i, val in enumerate(D):
    D[i] = int(artifice[i])

plt.imsave('hello_world.png', D, cmap=cm.gray)

相关问题 更多 >