Numpy dizisini görüntü olarak kaydetme


260

Numpy dizi türünde bir matris var. Bir görüntü olarak diske nasıl yazarım? Herhangi bir format çalışır (png, jpeg, bmp ...). Önemli bir kısıtlama, PIL'in mevcut olmamasıdır.


12
Sadece mutlaka aşağıdaki yanıtları ve geliyor ve bu soruyu bulma insanların bazıları bazı olmanın yukarıda listelenen kısıtlamayı uymayan dikkatinizi çekmek isteriz olmadan PIL . Bazı soranlar ve bazı cevaplar bu kısıtlamadan kaçındığından, burada olan ve PIL'e sahip olmalarını umursamayan herkesi ve PIL dışı yanıtları (yeni veya eski) PIL kullanıldığını belirtmek için teşvik ediyorum. orijinal kısıtlamayı karşılayan cevaplardan ayırt etmek için cevap türü.
Lindes

Yanıtlar:


54

PyPNG kullanabilirsiniz . Saf bir Python (bağımlılık yok) açık kaynaklı PNG kodlayıcı / kod çözücüdür ve NumPy dizilerini görüntü olarak yazmayı destekler .


4
Değerleri PNG için doğru aralıkta, genellikle 0..255 olarak ölçeklendirmeyi unutmayın. Sinir ağlarındaki değer aralıkları genellikle 0..1 veya -1..1'dir.
Tomáš Gavenčiak

8
PyPNG, dış bağımlılıklarını azaltan, ancak PIL ve türev sınıflarından çok daha yavaş hale getiren saf Python'dur. Örneğin, makinemde 3000x4000 görüntü kaydetmek PyPNG ile 4,05 saniye, ancak scipy.misc.imsave ile sadece 0,59 saniye sürdü (6 kat daha hızlı).
Zvika

@ TomášGavenčiak - scipy.misc.imsave artık Scipy'nin yeni sürümlerinde kullanımdan kaldırıldı. Aşağıdaki birkaç yorum, imageio.imwrite ('image_file.jpg', dizi) 'yi kullanmaktır
Psi-Ed

259

Bu PIL kullanır, ancak bazıları bunu yararlı bulabilir:

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

EDIT : Geçerli scipysürüm, min (veri) siyah ve max (veri) beyaz olacak şekilde tüm görüntüleri normalleştirmeye başladı. Verilerin tam gri seviyeleri veya tam RGB kanalları olması durumunda bu istenmeyen bir durumdur. Çözüm:

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

19
imsave yaşıyor ... / scipy / misc / pilutil.py PIL kullanan
denis

5
Kayıp olduğundan jpg'ye dönüştürürken dikkatli olun, böylece görüntüyü oluşturmak için kullanılan verileri tam olarak kurtaramayabilirsiniz.
Feanil

8
Bu artık scipy 0.19 kullanımında kullanımdan kaldırıldı - scipy.io.imwrite
g.stevo

6
"imsave SciPy 1.0.0'da kullanımdan kaldırıldı ve 1.2.0'da kaldırılacak" ( Scipy 1.1.0 doc )
noobar

15
scipy.misc.imsave kullanımdan kaldırıldı. içe aktarma imageio kullanma; imageio.imwrite ('dosya_adı.jpg', nmupy_array)
ChaosPredictor

228

PIL kullanarak bir cevap (yararlı olması durumunda).

"A" numpy dizisi verildi:

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

"jpeg" yerine istediğiniz her formatı koyabilirsiniz. Buradaki biçimler hakkında daha fazla ayrıntı


5
Görüntü bir PIL modülüdür. "Resim Image .__ file__" yazdır
Juh_

10
Biz burada dolaşıp PIL var olanlar için çok yararlı - Ben from PIL import Imagebunu açık tutmak için kullanacağını düşünüyorum ...
adaçayı

4
Bir RGB görüntünüz varsa, im = Image.fromarray (A) .convert ('RGB') kullanarak görüntüyü alabilirsiniz Daha fazla bilgi: stackoverflow.com/questions/4711880/…
Roger Veciana

RGB kodlamak için uint8 dizisinin üçüncü eksenini kullanmak bu yöntemle çalışır. PIL modülü "pip install pillow" kullanılarak kurulabilir.
bli

1
@Ludovico Verniani Görüntüleri deforme etmiyor, ancak renklerin sırasının RGB yerine BGR olduğu alışılmadık bir renk kodlaması kullanıyor.
Zvika

88

İle matplotlib:

import matplotlib

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

Matplotlib 1.3.1 ile çalışır, daha düşük sürüm hakkında bilmiyorum. Öğretiden:

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.

resim açıklamasını buraya girin


Bunu kullanarak. Ama hafıza sızıntısı çekiyor
SolessChong

matplotlib.imsave () yeni versiyonlarda
Vinay Lodha

6
Bu var matplotlib.pyplot.imsave2+ matplotlib içinde
Aleksei Petrenko

1
@HughPerkins Python 3'te PIL değiştirme olarak Yastık deneyin
christianbrodbeck

10
import matplotlib.pyplot as pltve sonraplt.imsave('name.png', array)
Alessandro Jacopson

61

Saf Python (2 ve 3), 3. taraf bağımlılığı olmayan bir snippet.

Bu işlev sıkıştırılmış, gerçek renkli (piksel başına 4 bayt) RGBAPNG'ler yazar.

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'')])

... Veriler, aşağıdaki gibi doğrudan ikili olarak açılan bir dosyaya yazılmalıdır:

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


2
Bu tam olarak aradığım şey gibi görünüyor, ancak bazı yorumlar ekleyebilir misiniz? Bunun bir dosyaya nasıl yazdığını anlamıyorum. Çıkışı daha önce açılmış bir dosyaya yazmak zorunda mısınız? Teşekkürler!
PhilMacKay

1
@PhilMacKay, verilerin sadece bir ikili dosyaya yazılması gerekir. yorum eklendi.
13:31

1
Birisi görüntünün ( buf) hangi formatta olması gerektiğini belirtebilir mi? Numpy dizi gibi görünmüyor ...
christianbrodbeck

1
@christianmbrodbeck, bir bytearray (RGBARGBA ...)
ideasman42

1
Teşekkürler @ ideasman42. Bu kodu Blender'da kullanmak için taşıdım .
emackey

57

Orada opencv(piton için buraya belgelerine ).

import cv2
import numpy as np

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

kaydetmekten başka daha fazla işlem yapmanız gerekiyorsa yararlıdır.


1
Neden 10 beden dizisi? Bu çözümde kullanılan 10 seçimine ne sebep oldu?
Gathide

3
@Gathide Dosyaya gelişigüzel numpy matrisi yazma örneği. Gerçek hayatta np.zeros((10,10))resminizle değiştirin .
Xocoatzin

5
cmap="gray"Resmi cv2 kullanarak kaydettiğimde nasıl bir şey ekleyebilirim ?
Mona Jalal

@Xocoatzin Kırık bağlantı?
jtlz2

1
@ jtlz2 Güncel bağlantı.
Xocoatzin

30

Matplotlib'iniz varsa şunları yapabilirsiniz:

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

Bu, çizimi kaydeder (resimlerin kendisi değil). resim açıklamasını buraya girin


10
Hayır, pyplot arabirimi için plt.figure () yöntemi gereksizdir. Ayrıca, sadece bir şekil penceresi görmek istiyorsanız plt.show () 'a ihtiyacınız vardır - bu durumda sadece bir görüntü dosyasını kaydetmek istendi, bu yüzden show () öğesini çağırmaya gerek yoktu.
DopplerShift

7
Ortaya çıkan görüntü dosyasının, yalnızca piksel verilerini değil, matlplotlib şeklinin eksenlerini ve gri alanını içereceğini unutmayın.
Dave

1
grafik arayüz desteği olmadan komut dosyasını uzak ana bilgisayarda çalıştırırsanız çalışmaz.
Temak

Görüntüyü bir not defterinde göstermek istiyorsanız, aşağıdakileri ekleyebilirsiniz: >> "IPython.display import Image" ve ardından >> "Image (dosyaadı = dosyaadı)"
Robert

Ekseni kaldırmak için:plt.axis('off')
yakout

15

Python'da 'skimage' kütüphanesini kullanabilirsiniz

Misal:

from skimage.io import imsave
imsave('Path_to_your_folder/File_name.jpg',your_array)

15

scipy.miscimsaveişlevi hakkında kullanımdan kaldırma uyarısı verir ve imageiobunun yerine kullanımını önerir .

import imageio
imageio.imwrite('image_name.png', img)

12

@ İdeasman42'nin cevabına ek:

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

Böylece şunları yapabilirsiniz:

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

Üreten test_grid.png:

Kırmızı, sarı, koyu su, gri ızgara

(Şeffaflık ayrıca yüksek baytı azaltarak da çalışır 0xff.)


8

Doğrudan çalışan tam bir örnek arayanlar için:

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

Ayrıca, yüksek kaliteli jpeg'ler istiyorsanız
.save(file, subsampling=0, quality=100)


6

matplotlib svn, görüntüleri sadece görüntü olarak kaydetmek için yeni bir işleve sahiptir - eksen yok vb. svn'yi yüklemek istemiyorsanız (matplotlib svn'de doğrudan image.py'dan kopyalanırsa, kısalık için öğreti):

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)

3

Dünya muhtemelen bir PNG dosyasına sayısal bir dizi yazmak için başka bir pakete ihtiyaç duymaz, ancak yeterince alamayanlar için son zamanlarda numpngwgithub'a koydum :

https://github.com/WarrenWeckesser/numpngw

ve pypi'de: https://pypi.python.org/pypi/numpngw/

Tek dış bağımlılık numpy.

İşte examplesdeponun dizininden ilk örnek . Temel çizgi basitçe

write_png('example1.png', img)

imgnümerik bir dizi nerede . Bu satırdan önceki tüm kod, içe aktarma ifadeleri ve oluşturulacak koddur 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)

İşte oluşturduğu PNG dosyası:

example1.png


Merak ediyorum, lib'in diğerlerinden nasıl farklı? Daha hızlı mı? Süslü özellikleri var mı?
F Lekschas

Birkaç özellik: (1) Numpy diziler kullanır. (2) Sadece python ve numpy kullanılarak yazılmıştır, bu yüzden C kütüphanesinin kurulmasını gerektirmez. (3) Animasyonlu PNG dosyaları oluşturabilir. (4) Matplotlib animasyonlarını animasyonlu PNG dosyaları olarak yazmak için bir sınıf sağlar.
Warren Weckesser

Teşekkürler! Saf python olan performans açısından stackoverflow.com/a/19174800/981933 ile nasıl karşılaştırıldığını merak ediyorum . Eski yöntem PIL'den 2 kat daha hızlıdır, ki bu oldukça harika. Eğer bu senin amacın değilse
boşver

2

Gri tonlamalı bir görüntü istediğinizi varsayarsak:

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

2

Imageio , animasyonlu görüntüler, video, hacimsel veriler ve bilimsel formatlar dahil olmak üzere çok çeşitli görüntü verilerini okumak ve yazmak için kolay bir arayüz sağlayan bir Python kütüphanesidir. Çapraz platformdur, Python 2.7 ve 3.4+ üzerinde çalışır ve kurulumu kolaydır.

Bu, gri tonlamalı görüntü için bir örnektir:

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)

1

Zaten [Py] Qt kullanıyorsanız, qimage2ndarray ile ilgilenebilirsiniz . 1.4 sürümünden (yeni çıkacak) başlayarak, PySide da destekleniyor ve imsave(filename, array)scipy's'e benzer küçük bir işlev olacak , ancak PIL yerine Qt kullanacak. 1.3 ile aşağıdaki gibi bir şey kullanın:

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'ün bir başka avantajı, bunun daha da hafif olmasını sağlayan saf bir python çözümü olmasıdır.)


1.4 sürümü çıktı. :-) (Cevabı buna göre düzenledim.)
hans_meine

1

Python ortamı Spyder'da çalışıyorsanız, değişken explorer'da diziyi sağ tıklatıp Görüntüyü Göster seçeneğini seçmekten daha kolay olamaz.

resim açıklamasını buraya girin

Bu, görüntüyü çoğunlukla PNG formatında dsik'e kaydetmenizi isteyecektir.

Bu durumda PIL kütüphanesine ihtiyaç duyulmaz.


1

Kullanın 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  

0

Numpy diziyi resim olarak kaydetmek için U'nun birkaç seçeneği vardır:

1) En iyisi: 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) ...

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.