2009-05-24 2 views
147

У меня есть матрица в типе массива Numpy. Как записать его на диск как образ? Работает любой формат (png, jpeg, bmp ...). Одним из важных ограничений является то, что PIL отсутствует.Сохранение массива Numpy как изображения

+8

Я просто хотел бы отметить, что некоторые из приведенных ниже ответов , и, конечно же, некоторые из людей, которые приходят и находят этот вопрос, не соответствуют указанному выше ограничению: _without_ [PIL] (http://www.pythonware.com/products/pil/). Поскольку некоторые опрошенные и некоторые ответы избегают этого ограничения, я призываю всех, кто здесь, и не возражает против того, чтобы PIL выглядел ниже, и любые ответы, не связанные с PIL (новые или старые), чтобы упомянуть, что они используются PIL тип ответа, чтобы отличить себя от ответов, удовлетворяющих первоначальному ограничению. – lindes

ответ

35

Вы можете использовать PyPNG. Это чистый Python (без зависимостей) с открытым исходным кодом PNG-кодировщик/декодер, и он supports пишет массивы NumPy как изображения.

25

Если вы Matplotlib, вы можете сделать:

import matplotlib.pyplot as plt 
plt.imshow(matrix) #Needs to be in row,col order 
plt.savefig(filename) 

Это сохранит сюжет (не само изображение). enter image description here

+0

Befoe imshow, нужно добавить plt.figure() и plt.show() – Framester

+8

Нет, для интерфейса pyplot plt.figure() является излишним. Кроме того, вам нужно только plt.show(), если вы хотите увидеть окно с рисунком, - в этом случае желательно сохранить файл изображения, поэтому не нужно было вызывать show(). – DopplerShift

+5

Обратите внимание, что полученный файл изображения будет содержать оси и серое значение фигуры matlplotlib, а не только данные пикселя. – Dave

4

Matplotlib СВН имеет новую функцию для сохранения изображений, как только изображение - без осей и т.д., это очень простая функция, чтобы портировать тоже, если вы не хотите, чтобы установить SVN (копируется прямо из image.py в Matplotlib СВН, убрана строка документации для краткости):

def imsave(fname, arr, vmin=None, vmax=None, cmap=None, format=None, origin=None): 
    from matplotlib.backends.backend_agg import FigureCanvasAgg as FigureCanvas 
    from matplotlib.figure import Figure 

    fig = Figure(figsize=arr.shape[::-1], dpi=1, frameon=False) 
    canvas = FigureCanvas(fig) 
    fig.figimage(arr, cmap=cmap, vmin=vmin, vmax=vmax, origin=origin) 
    fig.savefig(fname, dpi=1, format=format) 
182

Это использует PIL, но, возможно, некоторые из них могут оказаться полезным:

import scipy.misc 
scipy.misc.imsave('outfile.jpg', image_array) 

EDIT: текущий scipy ве rsion начал нормализовать все изображения, чтобы мин (данные) стали черными, а макс (данные) стали белыми. Это нежелательно, если данные должны быть точными уровнями серого или точными каналами RGB. Решение:

import scipy.misc 
scipy.misc.toimage(image_array, cmin=0.0, cmax=...).save('outfile.jpg') 
+13

imsave живет в .../scipy/misc/pilutil.py, который использует PIL – denis

+0

А, я не знал. Спасибо за ссылку. –

+2

Будьте осторожны при преобразовании в jpg, поскольку он является потерянным, и поэтому вы не сможете восстановить точные данные, используемые для создания изображения. – Feanil

93

Ответ с помощью PIL (только в случае, если это полезно).

дали NumPy массив "A":

from PIL import Image 
im = Image.fromarray(A) 
im.save("your_file.jpeg") 

вы можете заменить "JPEG" практически любой формат, который вы хотите. Более подробная информация о форматах here

+4

Изображение представляет собой модуль PIL. «Печать изображения .__ file__» –

+7

Очень полезно для тех из нас, кто бродил здесь и имеет PIL - я думаю, что буду использовать «из изображения импорта PIL», чтобы это было ясно ... – sage

+4

Если у вас есть изображение RGB , вы можете получить изображение, используя im = Image.fromarray (A) .convert ('RGB') Дополнительная информация: http://stackoverflow.com/questions/4711880/pil-using-fromarray-with-binary-data- and-writing-color-text –

44

Pure Python (2 & 3), фрагмент без зависимостей сторонних разработчиков.

Эта функция записывает сжатый, истинный цвет (4 байта на пиксель) RGBA PNG.

def write_png(buf, width, height): 
    """ buf: must be bytes or a bytearray in Python3.x, 
     a regular string in Python2.x. 
    """ 
    import zlib, struct 

    # reverse the vertical line order and add null bytes at the start 
    width_byte_4 = width * 4 
    raw_data = b''.join(
     b'\x00' + buf[span:span + width_byte_4] 
     for span in range((height - 1) * width_byte_4, -1, - width_byte_4) 
    ) 

    def png_pack(png_tag, data): 
     chunk_head = png_tag + data 
     return (struct.pack("!I", len(data)) + 
       chunk_head + 
       struct.pack("!I", 0xFFFFFFFF & zlib.crc32(chunk_head))) 

    return b''.join([ 
     b'\x89PNG\r\n\x1a\n', 
     png_pack(b'IHDR', struct.pack("!2I5B", width, height, 8, 6, 0, 0, 0)), 
     png_pack(b'IDAT', zlib.compress(raw_data, 9)), 
     png_pack(b'IEND', b'')]) 

...Эти данные должны быть записаны непосредственно в файл, открытый в двоичном виде, как в:

data = write_png(buf, 64, 64) 
with open("my_image.png", 'wb') as fd: 
    fd.write(data) 

+1

Кажется, это именно то, что я ищу, но не могли бы вы добавить комментарии? Я не вижу, как это записывается в файл. Вам нужно написать вывод в ранее открытом файле? Благодаря! – PhilMacKay

+1

@PhilMacKay, данные просто должны быть записаны в двоичный файл. добавил комментарий. – ideasman42

+1

Может ли кто-нибудь указать, в каком формате должно находиться изображение ('buf')? Кажется, это не массивный массив ... – christianbrodbeck

8

Приложение к решению @ ideaman42:

def saveAsPNG(array, filename): 
    import struct 
    if any([len(row) != len(array[0]) for row in array]): 
     raise ValueError, "Array should have elements of equal size" 

           #First row becomes top row of image. 
    flat = []; map(flat.extend, reversed(array)) 
           #Big-endian, unsigned 32-byte integer. 
    buf = b''.join([struct.pack('>I', ((0xffFFff & i32)<<8)|(i32>>24)) 
        for i32 in flat]) #Rotate from ARGB to RGBA. 

    data = write_png(buf, len(array[0]), len(array)) 
    f = open(filename, 'wb') 
    f.write(data) 
    f.close() 

Так что вы можете сделать:

saveAsPNG([[0xffFF0000, 0xffFFFF00], 
      [0xff00aa77, 0xff333333]], 'test_grid.png') 

Производство test_grid.png:

Grid of red, yellow, dark-aqua, grey

(. Прозрачность также работает, за счет снижения высокого байта из 0xff)

34

С matplotlib :

import matplotlib 

matplotlib.image.imsave('name.png', array) 

Работы с matplotlib 1.3.1, я не знаю о более низкой версии. Из: строку документации

Arguments: 
    *fname*: 
    A string containing a path to a filename, or a Python file-like object. 
    If *format* is *None* and *fname* is a string, the output 
    format is deduced from the extension of the filename. 
    *arr*: 
    An MxN (luminance), MxNx3 (RGB) or MxNx4 (RGBA) array. 

enter image description here

+0

Использование этого. Но страдание от утечки памяти – SolessChong

+0

matplotlib.imsave() в новых версиях –

+0

Это 'matplotlib.pyplot.imsave' в matplotlib 2+ –

1

Если вы решили использовать [Py] Qt уже, вы можете быть заинтересованы в qimage2ndarray. Начиная с версии 1.4 (только что выпущенной) поддерживается PySide, и будет крошечная функция imsave(filename, array), похожая на scipy, но используя Qt вместо PIL. С 1.3, просто использовать что-то вроде следующего:

qImage = array2qimage(image, normalize = False) # create QImage from ndarray 
success = qImage.save(filename) # use Qt's image IO functions for saving PNG/JPG/.. 

(Еще одно преимущество 1.4 является то, что это чистый раствор питон, который делает это еще более легкий.)

+0

Теперь релиз 1.4 отсутствует. :-) (я отредактировал ответ соответственно.) –

24

Там в opencv для питона (http://docs.opencv.org/trunk/doc/py_tutorials/py_tutorials.html) ,

import cv2 
import numpy as np 

cv2.imwrite("filename.png", np.zeros((10,10))) 

Полезно, если вам нужно сделать больше обработки, кроме сохранения.

+0

Почему массив размером 10? Что привело к выбору 10, используемых в этом решении? – Gathide

+1

@Gathide Как пример записи некоторой произвольной матрицы numpy в файл. В реальной жизни замените 'np.zeros ((10,10))' вашим изображением. – Xocoatzin

+1

Как я могу добавить что-то наподобие 'cmap =" gray "', когда я сохраняю изображение с помощью cv2? –

2

Мир, вероятно, не нуждается в еще один пакет для написания Numpy массива в файл PNG, но и для тех, кто не может получить достаточно, я недавно выставлен numpngw на GitHub:

https://github.com/WarrenWeckesser/numpngw

и на pypi: https://pypi.python.org/pypi/numpngw/

Единственная внешняя зависимость - numpy.

Вот первый пример из каталога репозитория examples.Существенная линия просто

write_png('example1.png', img) 

где img является Numpy массив. Весь код перед этой строкой - это операторы импорта и код для создания img.

import numpy as np 
from numpngw import write_png 


# Example 1 
# 
# Create an 8-bit RGB image. 

img = np.zeros((80, 128, 3), dtype=np.uint8) 

grad = np.linspace(0, 255, img.shape[1]) 

img[:16, :, :] = 127 
img[16:32, :, 0] = grad 
img[32:48, :, 1] = grad[::-1] 
img[48:64, :, 2] = grad 
img[64:, :, :] = 127 

write_png('example1.png', img) 

Вот файл PNG, который он создает:

example1.png

1

Предполагая, что вы хотите, изображение в оттенках серого:

im = Image.new('L', (width, height)) 
im.putdata(an_array.flatten().tolist()) 
im.save("image.tiff") 
Смежные вопросы