Как преобразовать массив Numpy в (и отобразить) изображение?

228

Я создал массив таким образом:

import numpy as np
data = np.zeros( (512,512,3), dtype=np.uint8)
data[256,256] = [255,0,0]

Я хочу, чтобы это отображало одну красную точку в центре изображения 512x512. (По крайней мере, для начала ... я думаю, что я могу выяснить остальное оттуда)

jlswint
источник
1
См. Также stackoverflow.com/questions/902761/… хотя этот наложил ограничение, что PIL не может быть использован.
Питер Хансен
Не могли бы вы рассмотреть вопрос об изменении принятого ответа на Питера ? Это позволяет избежать необходимости оборачивать объект вокруг массива numpy и записывать временный файл для отображения изображения.
Джозия Йодер

Ответы:

225

Вы можете использовать PIL для создания (и отображения) изображения:

from PIL import Image
import numpy as np

w, h = 512, 512
data = np.zeros((h, w, 3), dtype=np.uint8)
data[0:256, 0:256] = [255, 0, 0] # red patch in upper left
img = Image.fromarray(data, 'RGB')
img.save('my.png')
img.show()
unutbu
источник
3
Кажется, что есть ошибка. Вы создаете массив с размером (w,h,3), но так и должно быть (h,w,3), потому что индексирование в PIL отличается от индексирования в numpy. Есть связанный вопрос: stackoverflow.com/questions/33725237/…
fdermishin
1
@ user502144: Спасибо, что указали на мою ошибку. Я должен был создать массив формы (h,w,3). (Теперь это зафиксировано выше.) Длина первой оси может рассматриваться как количество строк в массиве, а длина второй оси - как число столбцов. Так что (h, w)соответствует массиву «высота» hи «ширина» w. Image.fromarrayпреобразует этот массив в изображение высоты hи ширины w.
Unutbu
1
img.show()не работайте в ноутбуке ipython. img_pil = Image.fromarray(img, 'RGB') display(img_pil.resize((256,256), PIL.Image.LANCZOS))
mrgloom
@unutbu этот метод, кажется, искажает изображения ... stackoverflow.com/questions/62293077/…
Людовико Верниани
285

Следующее должно работать:

from matplotlib import pyplot as plt
plt.imshow(data, interpolation='nearest')
plt.show()

Если вы используете Jupyter notebook / lab, используйте эту встроенную команду перед импортом matplotlib:

%matplotlib inline 
Стив Тджоа
источник
3
Это точнее, чем PIL. PIL изменяет / нормализует значения массива, тогда как pyplot использует фактические значения RGB как они есть.
GaryO
21
Может быть, стоит знать: если вы хотите отображать изображения в градациях серого, рекомендуется plt.gray()один раз вызвать код, чтобы переключить все последующие графики в градации серого. Не то, что хочет ОП, но все же полезно знать.
Cerno
2
Как сохранить это?
user334639
Файл "<ipython-input-29-29c784f62838>", строка 39 plt.show () ^ SyntaxError: недопустимый синтаксис
Мона Джалал,
1
@Cerno Кроме того, изображения в градациях серого должны иметь форму (h, w), а не (h, w, 1). Вы можете использовать, squeeze()чтобы устранить третье измерение:plt.imshow(data.squeeze())
Иосия Йодер
51

Кратчайший путь для использования scipy, как это:

from scipy.misc import toimage
toimage(data).show()

Для этого также необходимо установить PIL или подушку.

Аналогичный подход, также требующий PIL или Pillow, но который может вызвать другого зрителя :

from scipy.misc import imshow
imshow(data)
Питер Хансен
источник
Так что этот метод несовместим с Python 3.5 ...?
Кристофер
@bordeo, почему это было бы несовместимо с 3.5? Это просто импорт и пара вызовов функций.
Питер Хансен
PIL несовместим с 3.5 (не устанавливается)
Кристофер,
1
Ftr: вы можете сократить это дальше, используя непосредственно scipy.misc.imshow(data).
июня
3
toimageустарела в scipy-1.0.0 и удалена в 1.2.0 в пользу Pillow's Image.fromarray.
Сид
4

Используя pygame , вы можете открыть окно, получить поверхность в виде массива пикселей и манипулировать оттуда как хотите. Однако вам нужно будет скопировать ваш массив NumPy в массив Surface, что будет намного медленнее, чем выполнение реальных графических операций на самих поверхностях Pygame.

Стефан Кендалл
источник
3

Как показать изображения, хранящиеся в массиве с примерами (работает в блокноте Jupyter)

Я знаю, что есть более простые ответы, но этот даст вам понимание того, как изображения на самом деле тонут из массива.

Пример загрузки

from sklearn.datasets import load_digits
digits = load_digits()
digits.images.shape   #this will give you (1797, 8, 8). 1797 images, each 8 x 8 in size

Показать массив одного изображения

digits.images[0]
array([[ 0.,  0.,  5., 13.,  9.,  1.,  0.,  0.],
       [ 0.,  0., 13., 15., 10., 15.,  5.,  0.],
       [ 0.,  3., 15.,  2.,  0., 11.,  8.,  0.],
       [ 0.,  4., 12.,  0.,  0.,  8.,  8.,  0.],
       [ 0.,  5.,  8.,  0.,  0.,  9.,  8.,  0.],
       [ 0.,  4., 11.,  0.,  1., 12.,  7.,  0.],
       [ 0.,  2., 14.,  5., 10., 12.,  0.,  0.],
       [ 0.,  0.,  6., 13., 10.,  0.,  0.,  0.]])

Создайте пустые 10 x 10 участков для визуализации 100 изображений

import matplotlib.pyplot as plt
fig, axes = plt.subplots(10,10, figsize=(8,8))

Построение 100 изображений

for i,ax in enumerate(axes.flat):
    ax.imshow(digits.images[i])

Результат:

введите описание изображения здесь

Что делает axes.flat? Он создает нумерованный перечислитель, чтобы вы могли выполнять итерации по оси, чтобы рисовать на них объекты. Пример:

import numpy as np
x = np.arange(6).reshape(2,3)
x.flat
for item in (x.flat):
    print (item, end=' ')
Харви
источник
2

Используя подушку fromarray, например:

from PIL import Image
from numpy import *

im = array(Image.open('image.jpg'))
Image.fromarray(im).show()
user3322286
источник
1

Imaging Library Python может отображать изображения с помощью Numpy массивов. Взгляните на эту страницу для примера кода:

РЕДАКТИРОВАТЬ: Как указано в примечании внизу этой страницы, вы должны проверить последние заметки о выпуске, которые делают это намного проще:

http://effbot.org/zone/pil-changes-116.htm

АРС
источник
это не отвечает на вопрос
Джон Ktejik
0

Дополнение для этого с matplotlib. Мне показалось удобным делать задачи компьютерного зрения. Допустим, вы получили данные с dtype = int32

from matplotlib import pyplot as plot
import numpy as np

fig = plot.figure()
ax = fig.add_subplot(1, 1, 1)
# make sure your data is in H W C, otherwise you can change it by
# data = data.transpose((_, _, _))
data = np.zeros((512,512,3), dtype=np.int32)
data[256,256] = [255,0,0]
ax.imshow(data.astype(np.uint8))
user140536
источник