Làm cách nào để chuyển đổi một mảng numpy thành (và hiển thị) một hình ảnh?


228

Tôi đã tạo ra một mảng như vậy:

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

Những gì tôi muốn làm điều này là hiển thị một chấm đỏ duy nhất ở giữa hình ảnh 512x512. (Ít nhất là bắt đầu với ... Tôi nghĩ rằng tôi có thể tìm ra phần còn lại từ đó)


1
Xem thêm stackoverflow.com/questions/902761/, mặc dù điều đó áp đặt ràng buộc mà PIL không thể sử dụng.
Peter Hansen

Bạn có thể cân nhắc thay đổi câu trả lời được chấp nhận cho Peter's không? Cả hai đều tránh sự cần thiết phải bọc một đối tượng xung quanh mảng numpy và tránh viết một tệp tạm thời để hiển thị hình ảnh.
Josiah Yoder

Câu trả lời:


224

Bạn có thể sử dụng PIL để tạo (và hiển thị) hình ảnh:

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

3
Dường như có một lỗi. Bạn tạo mảng với kích thước (w,h,3), nhưng nó phải như vậy (h,w,3), bởi vì lập chỉ mục trong PIL khác với lập chỉ mục trong numpy. Có câu hỏi liên quan: stackoverflow.com/questions/33725237/ Cách
fdermishin

1
@ user502144: Cảm ơn bạn đã chỉ ra lỗi của tôi. Tôi nên đã tạo ra một mảng của hình dạng (h,w,3). (Bây giờ đã được sửa, ở trên.) Độ dài của trục thứ nhất có thể được coi là số lượng hàng trong mảng và chiều dài của trục thứ hai, số lượng cột. Vì vậy, (h, w)tương ứng với một mảng "chiều cao" hvà "chiều rộng" w. Image.fromarraychuyển đổi mảng này thành một hình ảnh về chiều cao hvà chiều rộng w.
unutbu

1
img.show()không làm việc trong máy tính xách tay ipython. img_pil = Image.fromarray(img, 'RGB') display(img_pil.resize((256,256), PIL.Image.LANCZOS))
mrgloom

@unutbu phương pháp này dường như làm biến dạng hình ảnh ... stackoverflow.com/questions/62293077/NH
Ludovico Verniani

285

Sau đây nên làm việc:

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

Nếu bạn đang sử dụng Jupyter notebook / lab, hãy sử dụng lệnh nội tuyến này trước khi nhập matplotlib:

%matplotlib inline 

3
Điều này chính xác hơn PIL. PIL hủy bỏ / bình thường hóa các giá trị mảng, trong khi pyplot sử dụng các giá trị RGB thực tế như hiện tại.
GaryO

21
Có thể tốt để biết: Nếu bạn muốn hiển thị hình ảnh thang độ xám, nên gọi plt.gray()một lần trong mã của bạn để chuyển tất cả các biểu đồ sau sang thang độ xám. Không phải những gì OP muốn nhưng vẫn tốt để biết.
Cerno

2
Làm thế nào để cứu nó?
dùng334639

Tệp "<ipython-input-29-29c784f62838>", dòng 39 plt.show () ^ SyntaxError: cú pháp không hợp lệ
Mona Jalal

1
@Cerno Ngoài ra, hình ảnh thang độ xám phải có hình dạng (h, w) chứ không phải (h, w, 1). Bạn có thể sử dụng squeeze()để loại bỏ chiều thứ ba:plt.imshow(data.squeeze())
Josiah Yoder

51

Con đường ngắn nhất là sử dụng scipy, như thế này:

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

Điều này đòi hỏi PIL hoặc Gối cũng được cài đặt.

Một cách tiếp cận tương tự cũng yêu cầu PIL hoặc Gối nhưng có thể gọi một người xem khác là:

from scipy.misc import imshow
imshow(data)

Vậy phương pháp này không tương thích với python 3.5 ...?
Christopher

@bordeo, tại sao nó không tương thích với 3.5? Nó chỉ là một nhập khẩu và một vài cuộc gọi chức năng.
Peter Hansen

PIL không tương thích với 3.5 (sẽ không cài đặt)
Christopher

1
Ftr: bạn có thể rút ngắn điều này hơn nữa bằng cách sử dụng trực tiếp scipy.misc.imshow(data).
dtk

3
toimageđã bị phản đối trong scipy-1.0.0 và bị xóa trong 1.2.0, có lợi cho Gối Image.fromarray.
Sid

4

Sử dụng pygame , bạn có thể mở một cửa sổ, lấy bề mặt dưới dạng một mảng pixel và thao tác theo ý muốn từ đó. Tuy nhiên, bạn sẽ cần phải sao chép mảng numpy của mình vào mảng bề mặt, tuy nhiên, việc này sẽ chậm hơn nhiều so với thực hiện các thao tác đồ họa thực tế trên chính bề mặt pygame.


3

Ví dụ, làm thế nào để hiển thị hình ảnh được lưu trữ trong mảng numpy (hoạt động trong sổ ghi chép Jupyter)

Tôi biết có những câu trả lời đơn giản hơn nhưng câu trả lời này sẽ cho bạn hiểu về cách hình ảnh thực sự bị chết đuối từ mảng numpy.

Tải ví dụ

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

Hiển thị mảng của một hình ảnh

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

Tạo các ô con 10 x 10 trống để hiển thị 100 hình ảnh

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

Vẽ 100 hình ảnh

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

Kết quả:

nhập mô tả hình ảnh ở đây

Không gì axes.flatlàm gì? Nó tạo ra liệt kê numpy để bạn có thể lặp qua trục để vẽ các đối tượng trên chúng. Thí dụ:

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

2

Sử dụng gối củaararray, ví dụ:

from PIL import Image
from numpy import *

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


0

Bổ sung để làm như vậy với matplotlib. Tôi thấy nó tiện dụng khi thực hiện các nhiệm vụ thị giác máy tính. Giả sử bạn có dữ liệu với 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))
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.