Menyimpan array Numpy sebagai gambar

261

Saya punya matriks dalam jenis array Numpy. Bagaimana saya menulisnya ke disk sebagai gambar? Semua format berfungsi (png, jpeg, bmp ...). Salah satu kendala penting adalah bahwa PIL tidak ada.

M456
sumber
12
Saya hanya ingin mencatat bahwa beberapa jawaban di bawah ini, dan tentunya beberapa orang yang datang dan menemukan pertanyaan ini, tidak memenuhi batasan yang tercantum di atas tanpa PIL . Karena beberapa penanya dan beberapa jawaban sama-sama menghindari kendala itu, saya mendorong siapa pun yang ada di sini dan tidak keberatan memiliki PIL untuk melihat di bawah, dan jawaban non-PIL (baru atau lama) untuk menyebutkan bahwa mereka adalah PIL-digunakan jenis jawaban, untuk membedakan diri dari jawaban yang memenuhi kendala asli.
lindes

Jawaban:

54

Anda bisa menggunakan PyPNG . Ini adalah Python murni (tanpa dependensi) open source PNG encoder / decoder dan mendukung penulisan array NumPy sebagai gambar.

dF.
sumber
4
Ingatlah untuk skala nilai ke rentang yang tepat untuk PNG, biasanya 0..255. Rentang nilai dalam jaringan saraf seringkali 0..1 atau -1..1.
Tomáš Gavenčiak
8
PyPNG adalah Python murni, yang mengurangi ketergantungan eksternal, tetapi membuatnya jauh lebih lambat dari PIL dan kelas turunannya. Misalnya, menyimpan gambar 3000x4000 di komputer saya membutuhkan 4,05 detik dengan PyPNG tetapi hanya 0,59 detik dengan scipy.misc.imsave (6x lebih cepat).
Zvika
@ TomášGavenčiak - scipy.misc.imsave sekarang tidak digunakan lagi dalam versi Scipy yang lebih baru. Alternatif beberapa komentar di bawah ini adalah dengan menggunakan imageio.imwrite ('image_file.jpg', array)
Psi-Ed
259

Ini menggunakan PIL, tetapi mungkin beberapa mungkin merasa berguna:

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

EDIT : Versi saat scipyini mulai menormalkan semua gambar sehingga min (data) menjadi hitam dan maks (data) menjadi putih. Ini tidak diinginkan jika data harus tingkat abu-abu yang tepat atau saluran RGB yang tepat. Solusinya:

import scipy.misc
scipy.misc.toimage(image_array, cmin=0.0, cmax=...).save('outfile.jpg')
Steve Tjoa
sumber
19
imsave tinggal di ... / scipy / misc / pilutil.py yang menggunakan PIL
denis
5
Berhati-hatilah saat mengonversi ke jpg karena itu lossy dan karenanya Anda mungkin tidak dapat memulihkan data yang digunakan untuk menghasilkan gambar.
Feanil
8
Ini sekarang ditinggalkan dalam penggunaan 0,19 scipy - scipy.io.imwrite
g.stevo
6
"imsave sudah ditinggalkan dalam SciPy 1.0.0, dan akan dihapus dalam 1.2.0" ( Scipy 1.1.0 doc )
noobar
15
scipy.misc.imsave sudah usang. gunakan import imageio; imageio.imwrite ('file_name.jpg', nmupy_array)
ChaosPredictor
228

Jawaban menggunakan PIL (kalau-kalau itu berguna).

diberi array numpy "A":

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

Anda dapat mengganti "jpeg" dengan hampir semua format yang Anda inginkan. Lebih detail tentang format di sini

migas
sumber
5
Gambar adalah modul PIL. Lakukan "cetak Gambar .__ file__"
Juh_
10
Sangat membantu bagi kita yang berkeliaran di sini dan memiliki PIL - saya pikir saya akan menggunakan from PIL import Imageuntuk menjernihkan ...
bijak
4
Jika Anda memiliki gambar RGB, Anda bisa mendapatkan gambar menggunakan im = Image.fromarray (A) .convert ('RGB') Info lebih lanjut: stackoverflow.com/questions/4711880/…
Roger Veciana
Menggunakan sumbu ketiga array uint8 untuk mengkode RGB berfungsi dengan metode ini. Modul PIL dapat dipasang menggunakan "pip install pillow".
bli
1
@Ludovico Verniani Ini tidak mengubah gambar, tetapi ia menggunakan pengkodean warna yang agak tidak umum di mana urutan warna adalah BGR daripada RGB.
Zvika
88

Dengan matplotlib:

import matplotlib

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

Bekerja dengan matplotlib 1.3.1, saya tidak tahu tentang versi yang lebih rendah. Dari docstring:

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.

masukkan deskripsi gambar di sini

christianbrodbeck
sumber
Menggunakan ini. Tetapi menderita kebocoran memori
SolessChong
matplotlib.imsave () dalam versi yang lebih baru
Vinay Lodha
6
Ada matplotlib.pyplot.imsavedi matplotlib 2+
Aleksei Petrenko
1
@HughPerkins mencoba Bantal sebagai pengganti PIL dengan Python 3
christianbrodbeck
10
import matplotlib.pyplot as pltdan kemudianplt.imsave('name.png', array)
Alessandro Jacopson
62

Pure Python (2 & 3), cuplikan tanpa dependensi pihak ketiga.

Fungsi ini menulis RGBAPNG's terkompresi, warna asli (4 byte per piksel) .

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 harus ditulis langsung ke file yang dibuka sebagai biner, seperti pada:

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

gagasanman42
sumber
2
Ini tampaknya persis apa yang saya cari, tetapi bisakah Anda menambahkan beberapa komentar? Saya tidak melihat bagaimana ini menulis ke file. Apakah Anda harus menulis output di file yang sebelumnya dibuka? Terima kasih!
PhilMacKay
1
@ PhilMacKay, data harus ditulis ke file biner. menambahkan komentar.
ideasman42
1
Bisakah seseorang menentukan format gambar ( buf) yang seharusnya? Tampaknya tidak menjadi array numpy ...
christianbrodbeck
1
@christianmbrodbeck, bytearray (RGBARGBA ...)
ideasman42
1
Terima kasih @ ideasman42. Saya porting kode ini untuk digunakan dalam Blender .
emackey
57

Ada opencvuntuk python ( dokumentasi di sini ).

import cv2
import numpy as np

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

berguna jika Anda perlu melakukan lebih banyak pemrosesan selain menyimpan.

Xocatzin
sumber
1
Mengapa berbagai ukuran 10? Apa yang menyebabkan pilihan 10 digunakan dalam solusi ini?
Gathide
3
@ Gatide Sama seperti contoh menulis beberapa matriks numpy sewenang-wenang ke file. Dalam kehidupan nyata ganti np.zeros((10,10))dengan gambar Anda.
Xocoatzin
5
Bagaimana saya bisa menambahkan sesuatu seperti cmap="gray"ketika saya menyimpan gambar menggunakan cv2?
Mona Jalal
@Xocoatzin Tautan Rusak?
jtlz2
1
@ jtlz2 Tautan yang diperbarui.
Xocoatzin
30

Jika Anda memiliki matplotlib, Anda dapat melakukan:

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

Ini akan menyimpan plot (bukan gambar itu sendiri). masukkan deskripsi gambar di sini

DopplerShift
sumber
10
Tidak, untuk antarmuka pyplot, plt.figure () tidak perlu. Selain itu, Anda hanya perlu plt.show () jika Anda ingin melihat jendela gambar juga - dalam hal ini hanya menyimpan file gambar yang diinginkan, jadi tidak perlu memanggil show ().
DopplerShift
7
Perhatikan bahwa file gambar yang dihasilkan akan berisi sumbu dan area abu-abu dari gambar matlplotlib - bukan hanya data piksel.
Dave
1
tidak akan berfungsi jika Anda menjalankan skrip pada host jarak jauh, ssh-ing tanpa skrip antarmuka grafis.
Temak
Jika Anda ingin menampilkan gambar dalam buku catatan, Anda dapat menambahkan yang berikut: >> "dari IPython.display import Image" dan kemudian >> "Image (nama file = nama file)"
Robert
Untuk menghapus poros:plt.axis('off')
yakout
15

Anda dapat menggunakan perpustakaan 'skimage' dengan Python

Contoh:

from skimage.io import imsave
imsave('Path_to_your_folder/File_name.jpg',your_array)
PURNENDU MISHRA
sumber
15

scipy.miscmemberikan peringatan penghentian tentang imsavefungsi dan menyarankan penggunaan imageiosebagai gantinya.

import imageio
imageio.imwrite('image_name.png', img)
Sefa
sumber
12

Tambahan untuk jawaban @ ideasman42:

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()

Jadi kamu bisa melakukan:

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

Memproduksi test_grid.png:

Kotak merah, kuning, aqua gelap, abu-abu

(Transparansi juga berfungsi, dengan mengurangi byte tinggi dari 0xff.)

Evgeni Sergeev
sumber
8

Bagi mereka yang mencari contoh langsung bekerja penuh:

from PIL import Image
import numpy

w,h = 200,100
img = numpy.zeros((h,w,3),dtype=numpy.uint8) # has to be unsigned bytes

img[:] = (0,0,255) # fill blue

x,y = 40,20
img[y:y+30, x:x+50] = (255,0,0) # 50x30 red box

Image.fromarray(img).convert("RGB").save("art.png") # don't need to convert

juga, jika Anda ingin jpeg berkualitas tinggi
.save(file, subsampling=0, quality=100)

Genangan air
sumber
6

matplotlib svn memiliki fungsi baru untuk menyimpan gambar hanya sebagai gambar - tidak ada sumbu dll. ini adalah fungsi yang sangat sederhana untuk backport juga, jika Anda tidak ingin menginstal svn (disalin langsung dari image.py di matplotlib svn, hapus docstring for brevity):

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)
Autoplektik
sumber
3

Dunia mungkin tidak membutuhkan paket lain untuk menulis array numpy ke file PNG, tetapi bagi mereka yang tidak bisa mendapatkan cukup, saya baru-baru ini memasang numpngwgithub:

https://github.com/WarrenWeckesser/numpngw

dan di pypi: https://pypi.python.org/pypi/numpngw/

Satu-satunya ketergantungan eksternal adalah numpy.

Inilah contoh pertama dari examplesdirektori repositori. Garis dasarnya sederhana saja

write_png('example1.png', img)

dimana imgarray numpy. Semua kode sebelum baris itu adalah pernyataan impor dan kode untuk dibuat 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)

Inilah file PNG yang dibuatnya:

contoh1.png

Warren Weckesser
sumber
Saya ingin tahu, bagaimana lib Anda berbeda dari yang lain? Apakah ini lebih cepat? Apakah ada fitur mewah?
F Lekschas
Beberapa fitur: (1) Menggunakan array numpy. (2) Ini ditulis hanya menggunakan python dan numpy, sehingga tidak memerlukan pustaka C untuk diinstal. (3) Dapat membuat file PNG animasi. (4) Ini menyediakan kelas untuk menulis animasi matplotlib sebagai file PNG animasi.
Warren Weckesser
Terima kasih! Saya ingin tahu bagaimana membandingkannya dengan stackoverflow.com/a/19174800/981933 dalam hal kinerja yang juga merupakan python murni. Metode sebelumnya di atas 2x lebih cepat dari PIL, yang cukup mengagumkan. Nevermind jika itu bukan tujuan Anda :)
F Lekschas
2

Dengan asumsi Anda menginginkan gambar skala abu-abu:

im = Image.new('L', (width, height))
im.putdata(an_array.flatten().tolist())
im.save("image.tiff")
Guillaume Lebreton
sumber
2

Imageio adalah perpustakaan Python yang menyediakan antarmuka yang mudah untuk membaca dan menulis berbagai data gambar, termasuk gambar animasi, video, data volumetrik, dan format ilmiah. Ini adalah lintas-platform, berjalan pada Python 2.7 dan 3.4+, dan mudah untuk diinstal.

Ini adalah contoh untuk gambar skala abu-abu:

import numpy as np
import imageio

# data is numpy array with grayscale value for each pixel.
data = np.array([70,80,82,72,58,58,60,63,54,58,60,48,89,115,121,119])

# 16 pixels can be converted into square of 4x4 or 2x8 or 8x2
data = data.reshape((4, 4)).astype('uint8')

# save image
imageio.imwrite('pic.jpg', data)
Denis Rasulev
sumber
1

Jika Anda sudah menggunakan [Py] Qt, Anda mungkin tertarik dengan qimage2ndarray . Dimulai dengan versi 1.4 (baru saja dirilis), PySide didukung juga, dan akan ada imsave(filename, array)fungsi kecil yang mirip dengan scipy's, tetapi menggunakan Qt bukan PIL. Dengan 1.3, cukup gunakan sesuatu seperti berikut:

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

(Keuntungan lain dari 1.4 adalah itu adalah solusi python murni, yang membuatnya lebih ringan.)

hans_meine
sumber
Rilis 1.4 keluar sekarang. :-) (Saya mengedit jawaban sesuai.)
hans_meine
1

Jika Anda bekerja di lingkungan python Spyder, maka itu tidak bisa lebih mudah daripada mengklik kanan array di explorer variabel, dan kemudian pilih opsi Tampilkan Gambar.

masukkan deskripsi gambar di sini

Ini akan meminta Anda untuk menyimpan gambar ke dsik, sebagian besar dalam format PNG.

PIL library tidak diperlukan dalam hal ini.

abunickabhi
sumber
1

Gunakan cv2.imwrite.

import cv2
assert mat.shape[2] == 1 or mat.shape[2] == 3, 'the third dim should be channel'
cv2.imwrite(path, mat) # note the form of data should be height - width - channel  
Christy Lee
sumber
1

untuk menyimpan array numpy sebagai gambar, U punya beberapa pilihan:

1) terbaik dari yang lain: OpenCV

 import cv2   
 cv2.imwrite('file name with extension(like .jpg)', numpy_array)

2) Matplotlib

  from matplotlib import pyplot as plt
  plt.imsave('file name with extension(like .jpg)', numpy_array)

3) PIL

  from PIL import Image
  image = Image.fromarray(numpy_array)
  image.save('file name with extension(like .jpg)')

4) ...

nima farhadi
sumber