Skip to content
Advertisement

Pyplot imshow incorrectly output black to white

I want to plot some letters and separate them by 4 equal zones according to the letter’s width and height. It just so happens that everything looks good until a zone has blank pixels, such as zone_0.jpg, zone_7 and zone_12 as seen in the images below. How can I make it so that the image box that have 255 for every value of the image 2d array be printed white?

text zoning

Here’s my code so far:

half_width = int(np.floor(width / 2))
half_height = int(np.floor(height / 2))
z11 = boxed[:half_height, :half_width]
z12 = boxed[:half_height, half_width:]
z21 = boxed[half_height:, :half_width]
z22 = boxed[half_height:, half_width:]

# plotting by zone
plt.figure(figsize=(4, 4), tight_layout=True)
plt.subplot(221)
plt.imshow(z11, cmap='gray')
plt.title('z11')
plt.subplot(222)
plt.imshow(z12, cmap='gray')
plt.title('z12')
plt.subplot(223)
plt.imshow(z21, cmap='gray')
plt.title('z21')
plt.subplot(224)
plt.imshow(z22, cmap='gray')
plt.title('z22')
plt.savefig(f'{zone_path}/zone_{i}.jpg')
plt.close()

So each zone variable (z11, z12, z21, z22) are 2d numpy arrays where each cell can contain either 0 (will output black) or 255 (will output white).

For example, focusing on zone_0.jpg, the z22 variable will only contain cells with 255 as the value:

z22 with only 255

but z11 will contain a mix of 0 or 255 values:

z11 contains 0 or 255

Logically thinking, there should be no issue since 255 should always output to white, so I wonder why this behaviour happens?

Advertisement

Answer

Matplotlib by default always scales the colormap so that the color map min color is the data min and the colormap max color is the data max. You could have just used 0 and 1 for your data values and gotten the same images. If you have the data min = max, the scale is apparently set such that the display will match the colormap min.

To assert the colormap scale with your current 0, 255 data, add the following to each plot call: vmin=0, vmax=255. These force the colormap range instead of using the data passed to the plot call. See matplotlib.pyplot.imshow documentation for details – all cmap-capable plot functions support this.

User contributions licensed under: CC BY-SA
3 People found this is helpful
Advertisement