2012-03-28 2 views
5

Я пытаюсь построить небольшое изображение в python, используя matplotlib, и хотел бы, чтобы отображаемые оси имели ту же форму, что и массив numpy, из которого он был сгенерирован, т. Е. Данные не подлежат повторной выборке. Другими словами, каждая запись в массиве должна соответствовать пикселю (или присутствию) на экране. Это кажется тривиальным, но даже после траления в интернете для некоторого времени, я не могу заставить его работать:matplotlib plot small image without resampling

import numpy as np 
import matplotlib.pyplot as plt 
import matplotlib.cm as cm 

X = np.random.rand(30,40) 

fig = plt.figure() 
fig.add_axes(aspect="equal",extent=[0, X.shape[1], 0, X.shape[0]]) 
ax = fig.gca() 
ax.autoscale_view(True, False, False) 
ax.imshow(X, cmap = cm.gray) 

plt.show() 
+2

выглядит так, как будто код, который вы предоставили, имеет трюк, прямоугольная форма (40x30) сохраняется на графическом изображении, а пределы оси соответствуют форме изображения. Мне что-то не хватает в вашем вопросе? – gcalmettes

+0

Извините, что моя фраза запутанна. Меня интересует что-то вроде функции imshow в matlab, где количество пикселей на экране соответствует количеству записей в матрице, т. Е. Оси не переустанавливаются в соответствии с размером фигуры. – user588241

+1

Вы хотите иметь изображение без интерполяции? Если это так, просто измените код 'imshow' на' matshow' или добавьте 'interpolation = 'ближайшее'' в качестве параметра функции imshow. – carla

ответ

5

У меня была такая же проблема. Если опция interpolation='nearest' для imshow не достаточно хороша, хорошо, если ваша главная цель - увидеть сырые, немасштабированные, неинтерполированные, не сбрасываемые пиксели в matplotlib, тогда вы не сможете победить figimage IMHO. Демонстрация:

import numpy as np 
import numpy.random 
import matplotlib.pyplot as plt 

a=256*np.random.rand(64,64) 

f0=plt.figure() 
plt.imshow(a,cmap=plt.gray()) 
plt.suptitle("imshow") 

f1=plt.figure() 
plt.figimage(a,cmap=plt.gray()) 
plt.suptitle("figimage") 

plt.show() 

Конечно, это означает отказ от осей (или их как-то рисование). Есть некоторые опции для figimage, которые позволяют перемещать изображение вокруг фигуры, поэтому я предполагаю, что можно было бы маневрировать ими поверх некоторых осей, созданных другими способами.

+1

В случае, если кто-то задается вопросом, единственный способ, которым я смог получить рисунок, чтобы работать без ничего на сюжете, кроме изображения в Ipython Notebook, было добавление пустого («выключенного») набора осей перед plt.show() , сродни этому сообщению S/O: http://stackoverflow.com/questions/9295026/matplotlib-plots-removing-axis-legends-and-white-spaces. В противном случае, это просто ничего не замышляло. –

1

Я не уверен, я полностью понимаю ваш вопрос. Означает ли это, что вам нужна ось x между 0 и X.shape [1] и ось y между 0 и X.shape [0]? В этом случае, этот код должен сделать трюк:

import numpy as np 
import matplotlib.pyplot as plt 
import matplotlib.cm as cm 

X = np.random.rand(30,40) 

fig = plt.figure() 

plt.xlim(0, X.shape[1]) 
plt.ylim(0, X.shape[0]) 

ax = fig.gca() 
ax.autoscale_view(True, False, False) 
ax.imshow(X, cmap = cm.gray) 

plt.show() 

Надеется, что это помогает

+0

Спасибо, извините, если мой вопрос был запутан. Я пытаюсь сделать что-то вроде imshow в Matlab, где оси внутри фигуры имеют тот же размер, что и массив, например. каждый пиксель на экране соответствует записи в матрице. Вышеупомянутое масштабирует массив и выравнивает его размер. – user588241

+0

Я только что нашел знакомый пост в stackoverflow, они используют аргумент интерполяции imshow: ax.imshow (X, cmap = cm.gray, extent = (0, X.shape [1], 0, X.shape [0]), интерполяция = 'ближайшая') Вот ссылка http: // stackoverflow.com/questions/6323737/make-a-2d-pixel-plot-with-matplotlib – nay

+0

Спасибо, используя интерполяцию ближайшего соседа, хорошо, но также я хотел бы, чтобы оси были маленькими, т. е. поэтому он более точно отражает истинный размер массив. В настоящее время кажется, что оси все еще масштабируются, чтобы соответствовать размеру фигуры. – user588241

1

Если вы знаете, родное разрешение вашего изображения, вы можете установить ДОИ аргумент к тому, что вы хотите в plt.figure(dpi=value).

Дополнительную информацию об изменении размера изображения можно найти на этом link.

3

Вы можете использовать следующий фрагмент кода для преобразования массива в PIL (Python Imaging Library). Полученное изображение будет иметь тот же размер, что и входной массив. Он может отображаться или сохраняться как изображение.

from PIL import Image 
from numpy import linspace, array, fromfunction, sin, cos 
from matplotlib import cm 


# scale array between vmin and vmax and encode it to uint8 (256 values) 
def scale(arr, vmin, vmax): 
    return (255*(arr - vmin)/(vmax - vmin)).clip(0, 255).astype('uint8') 

# convert a matplotlib colormap into a PIL palette 
def getpalette(cmap): 
    return (255.*array(map(lambda x: cmap(x)[0:3], linspace(0., 1.,256))).ravel()).astype('int') 


# a sample array 
data = fromfunction(lambda i,j: cos((i+j)/50)*sin(i/50.), (200, 300), dtype='float') 

# convert the float array to a PIL image 
im = Image.fromarray(scale(data, 0, 1)) 
im.putpalette(getpalette(cm.jet)) 
im.save('test.png') # or im.show() 

Единственное, что im.show() не очень хорошо, потому что он требует, чтобы зритель xv изображения и записывает временный файл. Таким образом, вы можете написать файл и загрузить его с помощью своего любимого средства просмотра изображений.