Reputation: 15
I have an array that is 50(rows) by 33(columns). I am importing it to a numpy array on python. The values on my array range from 0 to 4096, so I am scaling it to 0-255 and then I trying to create a grayscale image from it, and save it.
import numpy
from PIL import Image
data = numpy.loadtxt('result.txt',delimiter='\t',dtype=None)
rescaled = (255.0 / 4096 * (data)).astype(numpy.uint8)
image = Image.fromarray(rescaled)
image.save('test_fullsize.jpeg', quality=95)
This does not output any errors, however the produced image is only 50x33 pixels. This means the picture is very small(i can see that it is indeed the type of image I am looking for, however it is very very small)
I tried resizing the image by adding this line of code before I save it:
image = image.resize((480, 640), Image.ANTIALIAS)
However, that outputed a very pixelated(bad quality) 480,640 image. I need this image to be of a decent resolution/size to be able to put it on a poster.
Thank you.
Upvotes: 1
Views: 5640
Reputation: 3936
From what I understand, you're trying to display the numbers in your matrix as different shades of grey and make it large enough to fit on a poster. So, like @pandita, I would also use Matplotlib as this can be done pretty easily.
import matplotlib.pyplot as plt
import matplotlib.cm as cm
import numpy as np
height, width = 50, 33 #in pixels
spines = 'left', 'right', 'top', 'bottom'
labels = ['label' + spine for spine in spines]
tick_params = {spine : False for spine in spines}
tick_params.update({label : False for label in labels})
img = np.random.randint(0, 4097, (height, width))
img *= 255. / 4096
desired_width = 8 #in inches
scale = desired_width / float(width)
fig, ax = plt.subplots(1, 1, figsize=(desired_width, height*scale))
img = ax.imshow(img, cmap=cm.Greys_r, interpolation='none')
#remove spines
for spine in spines:
ax.spines[spine].set_visible(False)
#hide ticks and labels
ax.tick_params(**tick_params)
#preview
plt.show()
#save
fig.savefig('test.png', dpi=300)
Produces the following image ...
Upvotes: 3
Reputation: 143
You might just be able to zoom in on the smaller version of the file with whatever you're viewing it with, that would be a better solution I think. However, if you really need a higher resolution, try replacing
image = image.resize((480, 640), Image.ANTIALIAS)
with
image = image.resize((480, 640), Image.NEAREST)
or just
image = image.resize((480, 640))
as NEAREST
is the default for this method.
The second parameter to the resize method is the interpolation/filter used when resizing. ANTIALIAS
is a filter that reduces aliasing artifacts when downsampling. NEAREST
sets all pixels the coulour of the nearest pixel in the original image. This results in a very "blocky" or "pixely" look, which I'm guessing you want.
Source:http://effbot.org/imagingbook/image.htm
Upvotes: 0
Reputation: 4979
As an alternative approach to what @John1024 suggests, if your data is following some trends along the rows/columns, you possibly could spread the data across say 480x640 pixels and interpolate the missing values. Pandas or scipy could help with this.
If your data is not following any trends, you could have a collection of pixels represent your single data point, e.g. the value in the first row and column would cover 480/33 x 640/50 pixels.
You can do the latter via a number of ways:
Parsing through individual pixels
magnifier = 10
im = Image.new('RGB',(rows*magnifier,cols*magnifier))
pix = im.load()
for row in range(im.size[0]):
for col in range(im.size[1]):
value = rescaled[row/rescaled.shape[0], col/rescaled.shape[1]],rescaled[row/rescaled.shape[0], col/rescaled.shape[1]],rescaled[row/rescaled.shape[0], col/rescaled.shape[1]]
pix[row,col] = value
im.save('test_fullsize.jpeg', quality=95)
This results in very sharp edges without any blur at all.
Using matplotlib and scipy
import matplotlib.pyplot as plt
from scipy.ndimage.interpolation import zoom
# With interpolation
rescaled2 = zoom(rescaled,zoom=10)
# plt.imshow(rescaled2, cmap=plt.cm.hot) # Color map
plt.imshow(rescaled2, cmap=plt.cm.gray)
# Just the data
plt.imshow(rescaled, cmap=plt.cm.gray)
The results are still a little blurry. If interpolation is ok, you could use zoom
and oversample the image, i.e. make it much larger than you actually need it (two or three times of the final size, e.g.zoom=200
) and then reduce the size of the image with PIL. This would get rid of some of the blur.
Another alternative could be to use a different representation for the data, e.g. different sized circles for each data point, depending on what you'd like to communicate.
Upvotes: 1
Reputation: 113814
To summarize, you have 50x33 image and you want to upsize to get a "decent resolution/size to be able to put it on a poster."
This class of problem is called super-resolution. It is an active research area. Some super-resolution algorithms are available as part of the opencv
library. opencv
has a python port. You can read about the available super-resolution algorithms here.
Depending on the type of image that you have, achieving a nice-looking 640x480 resolution image starting from 50x33 could be a bit of a stretch for even the best algorithms. You may need to temper your goals.
Upvotes: 1