1

I have a 2D array of values in crud dimensions (65000x256). I need to plot this data to an image that has exactly one pixel for each value.

def save_image_data(data, cm, fn):
#Source https://fengl.org /2014/07/09/matplotlib-savefig-without-borderframe/   
    sizes = np.shape(data)
    height = float(sizes[0])
    width = float(sizes[1])

    fig = plt.figure()
    fig.set_size_inches(width/height, 1, forward=False)
    ax = plt.Axes(fig, [0., 0., 1., 1.])
    ax.set_axis_off()
    fig.add_axes(ax)

    ax.imshow(data, cmap=cm)
    plt.pause(1)
    plt.savefig(fn, dpi = height, transparent=False) 

    plt.close()

There are no error messages. However the resulting images are in very very very low DPI since there are white borders on top and bottom of the image.

example image

2 Answers2

1

If the only purpose for using matplotlib here is to get a colormap on the array, the easiest is to use plt.imsave.

import numpy as np
import matplotlib.pyplot as plt

data = np.random.rand(256,65000)

plt.imsave("output.png", data, cmap="viridis")

This produces a png image with the exact pixel dimensions of the array.

If the image shall contain other plotting elements produced with matplotlib, it becomes way more complicated. (I'd be happy to extent this answer with other options, but only if needed, so best leave a comment in that case.)

ImportanceOfBeingErnest
  • 321,279
  • 53
  • 665
  • 712
-1

I had to plot a 2d array the other day. The following worked for me:

my_img = # 2d array

plt.figure(figsize=(19,19))
plt.imshow(my_img, cmap='gray_r', vmin=my_img.min(), vmax=my_img.max())

plt.title('Title')

plt.savefig(path)
plt.show();

EDIT: Pixel related: from the docs:

aspect : {'equal', 'auto'} or float, optional Controls the aspect ratio of the axes. The aspect is of particular relevance for images since it may distort the image, i.e. pixel will not be square.

This parameter is a shortcut for explicitly calling Axes.set_aspect. See there for further details.

'equal': Ensures an aspect ratio of 1. Pixels will be square (unless pixel sizes are explicitly made non-square in data coordinates using extent). 'auto': The axes is kept fixed and the aspect is adjusted so that the data fit in the axes. In general, this will result in non-square pixels. If not given, use rcParams["image.aspect"] (default: 'equal').

EDIT2: Although I provided a solution to plotting a 2d array with square pixels, i.e. not distorted, it is true that I hadn't considered the actual size of the pixels. I found two answers on SO which address that issue already, which I think might help you:

Hope this helps!

89f3a1c
  • 1,430
  • 1
  • 14
  • 24
  • 2
    What in this answer will ensure that the saved image has one pixel per array entry, as the question asker requires? – gspr Jun 21 '19 at 13:55
  • @gspr Just edited the answer. The image it outputs is of the same size as the 2d array, so I'm pretty sure it's exactly what op needs. – 89f3a1c Jun 21 '19 at 14:03
  • So you're telling me that, in particular, setting `my_img` to be a 1x1 array, this will produce an image with 1 pixel? I think not. – gspr Jun 21 '19 at 15:37
  • You're right! Although plotting one 'pixel' per data in array, my answer still doesn't address the issue of the size of the drawn 'pixel'. Added links to answers which addressed that issue. Thanks for pointing it out! – 89f3a1c Jun 21 '19 at 16:20