我正在尝试根据pi的宇宙质量和将地球在海平面的重力常数转换为二进制来制作一幅画。我已经完成数学运算,并且尺寸正确,并且它应该小于ram的兆字节,但是我遇到了允许的最大尺寸超出值错误。
代码如下:
text.replace(/[\n\r\s\t]+/g, ' ')
我一直遇到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
处的错误,也许我的重塑太大了,但只比4k大一点。似乎对于gpu增强的colab这应该没问题。也不会在我的家用计算机上运行,并且出现相同的错误。可以用更多的ram固定吗?
答案 0 :(得分:0)
我无法重现您的问题,因为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)
答案 1 :(得分:0)
使其正常工作
问题是artifice = np.binary_repr(genesis)
创建了一个字符串。字符串由1348 * 4117 = 5549716
个数字组成,所有数字均为零和一。如果将字符串转换为python整数A = int(artifice)
,您将(A)等待很长时间,并且(B)得到一个不可迭代的对象。用np.array(A)
创建的数组将只有一个元素。
好消息是,您可以完全利用字符串artifice
已经是可迭代的事实来绕开耗时的步骤:
D = np.array(list(artifice), dtype=np.uint8).reshape(1348, 4117)
list(artifice)
步骤将花费几秒钟,因为它必须拆分字符串,但是其他所有步骤都应该非常快。
使用plt.imsave('hello_world.png', D, cmap=cm.gray)
可以很容易地进行绘图:
颜色图
保存图像时,您可以轻松地将颜色映射更改为coolwarm
或任何您想要的颜色。请记住,您的图片是二进制的,因此实际上只有两个值很重要:
plt.imsave('hello_world2.png', D, cmap=cm.coolwarm)
探索
您有机会在这里为图像添加大量色彩。通常,PNG为8位。例如,您可以从中获取字节来构造图像,而不是将genesis
转换为位。您也可以使用半字节(半字节)来构造具有16种颜色的索引图像。稍加填充,您甚至可以确保拥有三个数据点的倍数,并以多种方式创建全彩色RGB图像。我不会介绍更复杂的选项,但是我想探索从字节开始制作简单的图像。
5549716
位为693715 = 5 * 11 * 12613
字节(带有四个前导零位)。这是一个非常讨厌的因式分解,导致图像尺寸为55x12613,所以让我们删除上面的半字节:尽管693716
的因式分解与693715
一样,但是693714
的因式分解非常很好地融入了597 * 1162
。
您可以使用自己的to_bytes
方法将整数转换为字节数组:
from math import ceil
byte_genesis = genesis.to_bytes(ceil(genesis.bit_length() / 8), 'big')
我使用内置的ceil
而不是np.ceil
的原因是它返回的是整数而不是浮点数。
转换巨大的整数非常快,因为bytes
对象可以直接访问整数的数据:即使创建副本,它实际上也不会进行处理。由于bytes
和int
名义上都是不可变的,因此它甚至可以共享缓冲区。同样,您可以使用np.frombuffer
从bytes
创建一个numpy数组,作为对相同内存位置的视图:
img = np.frombuffer(byte_genesis, dtype=np.uint8)[1:].reshape(597, 1162)
[1:]
是切断前半字节所必需的,因为bytes_genesis
必须足够大以容纳整个genesis
。您也可以在bytes
端斩掉:
img = np.frombuffer(byte_genesis[1:], dtype=np.uint8).reshape(597, 1162)
结果相同。这是图片的样子:
plt.imsave('hello_world3.png', img, cmap=cm.viridis)
结果太大,无法上传(因为它不是二进制图像),但这是一个随机选择的示例:
我不确定这在美学上是否符合您的要求,但希望它为您提供了一个开始研究如何将大量数字转换为数据缓冲区的地方。
更多选项,因为这很有趣
我想在这里使用半字节而不是字节,因为那样会使每个像素具有16种颜色,而像素数则是其两倍。您可以从1开始获得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)
另一种选择(从某种意义上讲是相反的方向)根本不使用颜色图。相反,您可以将空间除以三倍,然后在RGB空间中生成自己的颜色。幸运的是,693714
的主要因素之一是3
。因此,您可以获得398x581的图片(693714 == 3 * 398 * 581
)。您如何解释数据甚至比平时更多。
我继续之前的旁注
使用黑白二进制图像,您可以控制图像的颜色,大小和方向。使用8位数据,您可以控制如何采样位(如4位示例中的8个或更少),解释的字节序,颜色图和图像大小。使用全色时,您可以将每个三元组视为单独的颜色,将整个数据集视为三个连续的颜色平面,甚至可以执行诸如对数组应用Bayer filter之类的操作。除了大小,顺序,每个样本的位数等其他选项外,所有其他选项。
下面将立即显示颜色三元组和三个颜色平面选项。
全彩色图像
要将每组3个连续字节视为RGB三元组,可以执行以下操作:
img = temp.reshape(398, 581, 3)
plt.imsave('hello_world5.png', img)
请注意在这种情况下没有颜色图。
将数据解释为三个颜色平面需要额外的步骤,因为plt.imsave
期望最后一个维度的大小为3。np.rollaxis
是一个很好的工具:
img = np.rollaxis(temp.reshape(3, 398, 581), 0, 3)
plt.imsave('hello_world6.png', img)