为什么NumPy的随机函数似乎在其生成的值中显示模式?

Ziy*_*her 14 python random numpy

我正在玩NumPy和Pillow,并且发现了一个有趣的结果,显然在NumPy random.random()结果中展示了一种模式.

图一 图像二 图三 图四

这里是生成和保存100个这些图像(种子0)的完整代码示例,以上是此代码生成的前四个图像.

import numpy as np
from PIL import Image

np.random.seed(0)
img_arrays = np.random.random((100, 256, 256, 3)) * 255
for i, img_array in enumerate(img_arrays):
    img = Image.fromarray(img_array, "RGB")
    img.save("{}.png".format(i))
Run Code Online (Sandbox Code Playgroud)

以上是使用PIL.Image.fromarray()四个不同的NumPy阵列创建的四个不同的图像,这些阵列numpy.random.random((256, 256, 3)) * 255用于在四个不同的Python实例中生成256乘256的RGB值网格(同样的事情也发生在同一个实例中).

我注意到这只发生(在我的有限测试中)当图像的宽度和高度是2的幂时,我不知道如何解释它.

虽然这可能是很难看到,由于浏览器的抗锯齿(你可以下载图片,并查看它们在图像浏览器与无抗锯齿),还有像素的清晰紫褐色列每8列从第三列开始每一个形象.为了确保这一点,我在1​​00张不同的图像上进行了测试,他们都遵循了这种模式.

这里发生了什么?我猜测,这样的模式是,人们总是说用在需要真正的随机性加密安全随机数生成器的原因,但有背后的原因,这是特别发生的具体的解释吗?

PM *_*ing 16

不要责怪Numpy,责怪PIL/Pillow.;)你正在生成浮点数,但是PIL期望整数,并且它的浮点转换为int并不是我们想要的.需要进一步的研究来确定PIL到底做什么......

同时,您可以通过将值显式转换为无符号8位整数来消除这些行:

img_arrays = (np.random.random((100, 256, 256, 3)) * 255).astype(np.uint8)
Run Code Online (Sandbox Code Playgroud)

正如FHTMitchell在评论中指出的那样,一种更有效的形式是

img_arrays = np.random.randint(0, 256, (100, 256, 256, 3), dtype=np.uint8) 
Run Code Online (Sandbox Code Playgroud)

这是修改过的代码的典型输出:

使用Numpy制作的随机图像


PIL层Image.fromarray功能有一个已知的bug,描述在这里.你看到的行为可能与那个bug有关,但我猜它可能是一个独立的行为.;)

FWIW,这里是我对链接问题上提到的bug所做的一些测试和解决方法.

  • 或者`np.random.randint(0,256,(100,256,256,3),dtype = np.unit8)` (2认同)
  • @ZiyadEdher 两件事的力量是因为它每 8 个像素发生一次。因此,如果同一列中总是出现 8 的倍数,则列就会显示,因此宽度必须是 8 的倍数(其中每个 2 的幂都是 2 以上)。 (2认同)