问题
There should be some kinda puzzle for me.
Accordingly to PIL documentation it has different image modes (as 1, L, 8, RGB, RGBA, and so on), but I was interested about mode '1' (1-bit pixels, black and white, stored with one pixel per byte).
I've created 2 matrices size 100 by 100: first only zeroes (np.zeros) and second only ones (np.ones), expecting totally black image with ones, and white image with zeros in mode '1' for Black and White image only.
Picture of result
Question: what I'm doing wrong?
UPD. i've tried using np.dtype uint8, didn't worked:
Final acceptable UPD: Seem there is a PIL bug, what wasn't fixed for some time, so then you should be using a workarond to create a white rectangle that way. Strange but now I'm not even sure what mode '1' is even meant for :D
回答1:
Regarding the original issue, this is the shortest version, which works for me:
Image.fromarray(255 * np.ones((100, 100), np.uint8), '1')
I get a proper all white image.
As pointed out earlier, when converting to mode "1", dithering is activated by default. So, maybe the intention of mode "1" is exactly that: Providing a fast way to create dithered images. Let's see this short example:
from matplotlib import pyplot as plt
import numpy as np
from PIL import Image
plt.figure(1, figsize=(15, 5))
# Open some image
img = Image.open('path/to/your/image.png')
plt.subplot(1, 3, 1), plt.imshow(img)
# Convert to '1'; dithering activated by default
plt.subplot(1, 3, 2), plt.imshow(img.convert('1'))
# Convert to '1'; dithering deactivated
plt.subplot(1, 3, 3), plt.imshow(img.convert('1', dither=Image.NONE))
plt.tight_layout()
plt.show()
That'd be the output:
The dithered image quite looks like a usual grayscale image when small enough. When dithering is deactivated (right image), you actually get a thresholded image, where all values >= 128 are set to white, or black otherwise.
Hope that helps!
-----------------------
System information
-----------------------
Python: 3.8.1
Matplotlib: 3.2.0rc1
NumPy: 1.18.1
Pillow: 7.0.0
-----------------------
回答2:
You need to specify the dtype
when you create the arrays, else you get something like int64
:
im = np.zeros((100,100), dtype=np.uint8)
回答3:
There are two problems with your second case Image.fromarray(numpy.ones((100, 100)), '1')
numpy.ones(...)
creates a value of one, which has only one of the 8 bits set. You need a value of 255 to set all eight bits- you need to explicitly set the numpy dtype to
uint8
from PIL import Image
import numpy
white_image = Image.fromarray(numpy.full(shape=(100, 100), fill_value=255, dtype=numpy.uint8), '1')
This will produce a pure white image like you want.
来源:https://stackoverflow.com/questions/59672473/strange-pil-image-fromarray-behaviour-with-numpy-zeros-and-ones-in-mode-1