Bagaimana cara mengonversi array numpy ke (dan menampilkan) gambar?

228

Karena itu saya telah membuat array:

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

Yang ingin saya lakukan adalah menampilkan satu titik merah di tengah gambar 512x512. (Setidaknya untuk memulai dengan ... Saya pikir saya bisa mencari tahu sisanya dari sana)

terima kasih
sumber
1
Lihat juga stackoverflow.com/questions/902761/... meskipun yang memberlakukan batasan bahwa PIL tidak dapat digunakan.
Peter Hansen
Bisakah Anda mempertimbangkan untuk mengubah jawaban yang diterima untuk jawaban Peter ? Keduanya menghindari kebutuhan untuk membungkus objek di sekitar array yang numpy dan menghindari menulis file temp untuk menampilkan gambar.
Josiah Yoder

Jawaban:

225

Anda dapat menggunakan PIL untuk membuat (dan menampilkan) gambar:

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
sumber
3
Tampaknya ada bug. Anda membuat array dengan ukuran (w,h,3), tetapi seharusnya (h,w,3), karena pengindeksan di PIL berbeda dari pengindeksan di numpy. Ada pertanyaan terkait: stackoverflow.com/questions/33725237/…
fdermishin
1
@ user502144: Terima kasih telah menunjukkan kesalahan saya. Seharusnya saya membuat array bentuk (h,w,3). (Sekarang sudah diperbaiki, di atas.) Panjang sumbu pertama dapat dianggap sebagai jumlah baris dalam array, dan panjang sumbu kedua, jumlah kolom. Jadi (h, w)sesuai dengan array "tinggi" hdan "lebar" w. Image.fromarraymengubah susunan ini menjadi gambar dengan tinggi hdan lebar w.
unutbu
1
img.show()tidak berfungsi di notebook ipython. img_pil = Image.fromarray(img, 'RGB') display(img_pil.resize((256,256), PIL.Image.LANCZOS))
mrgloom
@unutbu metode ini tampaknya mendistorsi gambar ... stackoverflow.com/questions/62293077/…
Ludovico Verniani
285

Berikut ini harus bekerja:

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

Jika Anda menggunakan notebook / lab Jupyter, gunakan perintah inline ini sebelum mengimpor matplotlib:

%matplotlib inline 
Steve Tjoa
sumber
3
Ini lebih akurat daripada PIL. PIL mengubah skala / menormalkan nilai array, sedangkan pyplot menggunakan nilai RGB sebenarnya.
GaryO
21
Mungkin bagus untuk diketahui: Jika Anda ingin menampilkan gambar skala abu-abu, disarankan untuk memanggil plt.gray()sekali dalam kode Anda untuk mengalihkan semua grafik berikut ke skala abu-abu. Bukan apa yang diinginkan OP tapi bagus untuk diketahui.
Cerno
2
Bagaimana cara menyimpannya?
user334639
File "<ipython-input-29-29c784f62838>", baris 39 plt.show () ^ SyntaxError: sintaks tidak valid
Mona Jalal
1
@Cerno Juga, gambar skala abu-abu harus memiliki bentuk (h, w) daripada (h, w, 1). Anda dapat menggunakan squeeze()untuk menghilangkan dimensi ketiga:plt.imshow(data.squeeze())
Josiah Yoder
51

Jalur terpendek adalah untuk digunakan scipy, seperti ini:

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

Ini membutuhkan PIL atau Bantal untuk dipasang juga.

Pendekatan serupa juga membutuhkan PIL atau Bantal tetapi yang dapat meminta pengunjung yang berbeda adalah:

from scipy.misc import imshow
imshow(data)
Peter Hansen
sumber
Jadi metode ini tidak kompatibel dengan python 3.5 ...?
Christopher
@ordeo, mengapa itu tidak sesuai dengan 3,5? Itu hanya impor dan beberapa panggilan fungsi.
Peter Hansen
PIL tidak kompatibel dengan 3,5 (tidak akan menginstal)
Christopher
1
Ftr: Anda dapat mempersingkat ini lebih lanjut dengan langsung menggunakan scipy.misc.imshow(data).
dtk
3
toimagesudah ditinggalkan di scipy-1.0.0 dan dihapus di 1.2.0, mendukung Pillow Image.fromarray.
Sid
4

Menggunakan pygame , Anda dapat membuka jendela, mendapatkan permukaan sebagai array piksel, dan memanipulasi seperti yang Anda inginkan dari sana. Anda harus menyalin array numpy Anda ke array permukaan, yang akan jauh lebih lambat daripada melakukan operasi grafis yang sebenarnya pada permukaan pygame sendiri.

Stefan Kendall
sumber
3

Bagaimana menampilkan gambar yang disimpan dalam array numpy dengan contoh (berfungsi di notebook Jupyter)

Saya tahu ada jawaban yang lebih sederhana tetapi yang ini akan memberi Anda pemahaman tentang bagaimana gambar benar-benar tenggelam dari array numpy.

Muat contoh

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

Tampilan array dari satu gambar

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

Buat kosong 10 x 10 subplot untuk memvisualisasikan 100 gambar

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

Merencanakan 100 gambar

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

Hasil:

masukkan deskripsi gambar di sini

Apa yang axes.flatharus dilakukan Itu menciptakan enumerator numpy sehingga Anda dapat beralih pada poros untuk menggambar objek pada mereka. Contoh:

import numpy as np
x = np.arange(6).reshape(2,3)
x.flat
for item in (x.flat):
    print (item, end=' ')
Harvey
sumber
2

Menggunakan bantal dariarray, misalnya:

from PIL import Image
from numpy import *

im = array(Image.open('image.jpg'))
Image.fromarray(im).show()
pengguna3322286
sumber
0

Tambahan untuk melakukannya dengan matplotlib. Saya merasa berguna melakukan tugas visi komputer. Katakanlah Anda mendapat data dengan 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))
pengguna140536
sumber