บันทึกอาร์เรย์ Numpy เป็นรูปภาพ


260

ฉันมีเมทริกซ์ในประเภทของ Numpy array ฉันจะเขียนมันลงในดิสก์เป็นรูปภาพได้อย่างไร รูปแบบใดก็ได้ที่ทำงาน (png, jpeg, bmp ... ) ข้อ จำกัด ที่สำคัญอย่างหนึ่งคือไม่มี PIL


12
ฉันต้องการเพียงเพื่อให้ทราบว่าบางคำตอบด้านล่างและแน่นอนบางคนที่มาและพบว่าคำถามนี้ไม่เป็นไปตามข้อ จำกัด ดังกล่าวข้างต้นของการเป็นโดยไม่ต้อง PIL เนื่องจากผู้ถามและคำตอบบางอย่างหลีกเลี่ยงข้อ จำกัด ฉันจึงแนะนำให้ทุกคนที่อยู่ที่นี่และไม่รังเกียจที่จะดู PIL ด้านล่างและคำตอบที่ไม่ใช่ PIL (ใหม่หรือเก่า) เพื่อพูดถึงว่าพวกเขาใช้ PIL อยู่ ชนิดของคำตอบเพื่อแยกความแตกต่างจากคำตอบที่ตรงตามข้อ จำกัด เดิม
lindes

ดูเหมือนว่าเกี่ยวข้อง: stackoverflow.com/questions/33480297/viewing-npy-images
xxx ---

คำตอบ:


54

คุณสามารถใช้PyPNG มันเป็นงูหลามบริสุทธิ์ (ไม่มีการพึ่งพา) โอเพนซอร์ส PNG เข้ารหัส / ถอดรหัสและสนับสนุนการเขียนอาร์เรย์ NumPy เป็นภาพ


4
อย่าลืมปรับขนาดค่าให้อยู่ในช่วงที่เหมาะสมสำหรับ PNG โดยปกติคือ 0..255 ช่วงของค่าในเครือข่ายประสาทเทียมมักจะเป็น 0..1 หรือ -1..1
TomášGavenčiak

8
PyPNG เป็น Python แท้ซึ่งลดการพึ่งพาภายนอก แต่ทำให้ช้ากว่า PIL และคลาสที่ได้รับ ตัวอย่างเช่นการบันทึกภาพขนาด 3000x4000 ในเครื่องของฉันใช้เวลา 4.05 วินาทีกับ PyPNG แต่เพียง 0.59 วินาทีกับ scipy.misc.imsave (เร็วขึ้น 6x)
Zvika

@ TomášGavenčiak - scipy.misc.imsave ได้เลิกใช้แล้วใน Scipy เวอร์ชันใหม่ อีกทางเลือกหนึ่งความคิดเห็นด้านล่างคือการใช้ imageio.imwrite ('image_file.jpg', อาร์เรย์)
Psi-Ed

259

สิ่งนี้ใช้ PIL แต่บางทีบางคนอาจเห็นว่ามีประโยชน์:

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

แก้ไข : scipyรุ่นปัจจุบันเริ่มที่จะทำให้ปกติทุกภาพเพื่อให้ min (data) กลายเป็นสีดำและ max (data) กลายเป็นสีขาว สิ่งนี้ไม่พึงประสงค์หากข้อมูลควรเป็นระดับสีเทาหรือช่อง RGB ที่แน่นอน การแก้ไขปัญหา:

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

19
ชีวิตใน imsave ... / SciPy / เบ็ดเตล็ด / pilutil.py ซึ่งใช้ PIL
เดนิส

5
ใช้ความระมัดระวังเมื่อแปลงเป็น jpg เนื่องจากมีความสูญเสียดังนั้นคุณอาจไม่สามารถกู้คืนข้อมูลที่แน่นอนที่ใช้ในการสร้างภาพได้
Feanil

8
นี่เลิกใช้แล้วใน scipy 0.19 การใช้งาน - scipy.io.imwrite
g.stevo

6
"imsave เลิกใช้แล้วใน SciPy 1.0.0 และจะถูกลบใน 1.2.0" ( Scipy 1.1.0 doc )
noobar

15
scipy.misc.imsave เลิกใช้แล้ว ใช้ imageio นำเข้า imageio.imwrite ('file_name.jpg', nmupy_array)
ChaosPredictor

228

คำตอบที่ใช้PIL (ในกรณีที่มีประโยชน์)

รับอาร์เรย์ numpy "A":

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

คุณสามารถแทนที่ "jpeg" ด้วยเกือบทุกรูปแบบที่คุณต้องการ รายละเอียดเพิ่มเติมเกี่ยวกับรูปแบบที่นี่


5
ภาพเป็นโมดูลของ PIL ทำ "print Image .__ file__"
Juh_

10
มีประโยชน์มากสำหรับพวกเราที่หลงทางที่นี่และมี PIL - ฉันคิดว่าฉันจะใช้from PIL import Imageเพื่อให้ชัดเจน ...
ปราชญ์

4
หากคุณมีภาพ RGB คุณสามารถรับภาพโดยใช้ im = Image.fromarray (A) .convert ('RGB') ข้อมูลเพิ่มเติม: stackoverflow.com/questions/4711880/…
Roger Veciana

การใช้แกนที่สามของอาร์เรย์ uint8 ไปยังรหัส RGB ทำงานได้กับวิธีนี้ โมดูล PIL สามารถติดตั้งได้โดยใช้ "pip pip pillow"
bli

1
@ Ludovico Verniani มันไม่ได้บิดเบือนภาพ แต่มันใช้การเข้ารหัสสีที่ค่อนข้างแปลกซึ่งลำดับของสีเป็น BGR มากกว่า RGB
Zvika

87

ด้วยmatplotlib:

import matplotlib

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

ทำงานร่วมกับ matplotlib 1.3.1 ฉันไม่รู้เกี่ยวกับเวอร์ชั่นที่ต่ำกว่า จาก 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.

ป้อนคำอธิบายรูปภาพที่นี่


ใช้สิ่งนี้ แต่ความทุกข์จากการรั่วไหลของหน่วยความจำ
SolessChong

matplotlib.imsave () ในรุ่นที่ใหม่กว่า
Vinay Lodha

6
มันmatplotlib.pyplot.imsaveอยู่ใน matplotlib 2+
Aleksei Petrenko

1
@HughPerkins ลองใช้หมอนแทน PIL ใน Python 3
christianbrodbeck

10
import matplotlib.pyplot as pltและจากนั้นplt.imsave('name.png', array)
Alessandro Jacopson

61

Pure Python (2 & 3) ตัวอย่างข้อมูลที่ไม่มีการอ้างอิงจากบุคคลที่สาม

ฟังก์ชั่นนี้เขียนไฟล์บีบอัด, สีจริง (4 ไบต์ต่อพิกเซล) RGBAPNG ของ

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 fh:
    fh.write(data)


2
ดูเหมือนจะเป็นสิ่งที่ฉันกำลังมองหา แต่คุณสามารถเพิ่มความคิดเห็นได้ไหม? ฉันไม่เห็นว่าสิ่งนี้เขียนไปยังไฟล์อย่างไร คุณต้องเขียนผลลัพธ์ในไฟล์ที่เปิดก่อนหน้านี้หรือไม่? ขอบคุณ!
PhilMacKay

1
@PhilMacKay ข้อมูลจะต้องถูกเขียนลงในไฟล์ไบนารี เพิ่มความคิดเห็น
ideasman42

1
ใครสามารถระบุรูปแบบของภาพ ( buf) ที่ควรจะเป็น ดูเหมือนว่ามันจะไม่ใช่อาร์เรย์ที่มีค่ามาก ...
christianbrodbeck

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

1
ขอบคุณ @ ideasman42 ฉันรังเพลิงรหัสนี้เพื่อใช้ในการปั่น
emackey

57

มีopencvไว้สำหรับหลาม ( เอกสารประกอบที่นี่ )

import cv2
import numpy as np

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

มีประโยชน์ถ้าคุณต้องการทำการประมวลผลอื่นนอกเหนือจากการบันทึก


1
ทำไมต้องมีอาร์เรย์ขนาด 10 อะไรนำไปสู่การเลือก 10 ข้อที่ใช้ในการแก้ปัญหานี้?
Gathide

3
@Gathide เช่นเดียวกับตัวอย่างของการเขียนเมทริกซ์ numpy ไปยังไฟล์ ในชีวิตจริงแทนที่np.zeros((10,10))ด้วยภาพของคุณ
Xocoatzin

5
ฉันจะเพิ่มสิ่งที่ชอบได้อย่างไรcmap="gray"เมื่อฉันบันทึกภาพโดยใช้ cv2
Mona Jalal

@Xocoatzin ลิงก์เสียหรือไม่
jtlz2

1
@ jtlz2 ลิงก์ที่อัปเดตแล้ว
Xocoatzin

30

หากคุณมี matplotlib คุณสามารถทำได้:

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

สิ่งนี้จะบันทึกพล็อต (ไม่ใช่ภาพเอง) ป้อนคำอธิบายรูปภาพที่นี่


10
ไม่สำหรับอินเตอร์เฟส pyplot นั้น plt.figure () ไม่จำเป็น นอกจากนี้คุณจำเป็นต้องใช้ plt.show () หากคุณต้องการเห็นหน้าต่างรูปเช่นกัน - ในกรณีนี้ต้องการบันทึกไฟล์รูปภาพเท่านั้นดังนั้นจึงไม่จำเป็นต้องเรียก show ()
DopplerShift

7
โปรดทราบว่าไฟล์ภาพที่ได้จะมีแกนและพื้นที่สีเทาของรูป matlplotlib ไม่ใช่แค่ข้อมูลพิกเซล
เดฟ

1
จะไม่ทำงานหากคุณเรียกใช้สคริปต์ของคุณบนรีโมตโฮสต์โดยไม่ได้รับการสนับสนุนจากส่วนต่อประสานกราฟิก
Temak

หากคุณต้องการแสดงภาพในสมุดบันทึกคุณสามารถเพิ่มสิ่งต่อไปนี้: >> "จาก IPython.display Import Image" และจากนั้น >> "Image (filename = filename)"
Robert

ในการลบแกนออก:plt.axis('off')
yakout

15

คุณสามารถใช้ไลบรารี 'skimage' ใน Python

ตัวอย่าง:

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

15

scipy.miscให้คำเตือนการเลิกใช้งานเกี่ยวกับimsaveฟังก์ชันและแนะนำการใช้งานimageioแทน

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

12

ภาคผนวกคำตอบของ @ 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()

ดังนั้นคุณสามารถทำได้:

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

ผลิตtest_grid.png:

ตารางของสีแดง, สีเหลือง, สีดำน้ำ, สีเทา

(ความโปร่งใสยังทำงานได้โดยลดไบต์สูงจาก0xff)


8

สำหรับผู้ที่กำลังมองหาตัวอย่างการทำงานโดยตรงอย่างสมบูรณ์:

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

นอกจากนี้หากคุณต้องการ jpeg คุณภาพสูง
.save(file, subsampling=0, quality=100)


6

matplotlib svn มีฟังก์ชั่นใหม่ในการบันทึกภาพเป็นเพียงภาพ - ไม่มีแกน ฯลฯ มันเป็นฟังก์ชั่นที่ง่ายมากสำหรับ backport เช่นกันหากคุณไม่ต้องการติดตั้ง svn (คัดลอกโดยตรงจาก image.py ใน matplotlib svn ลบ docstring สำหรับความกะทัดรัด):

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

โลกอาจไม่จำเป็นต้องมีแพ็คเกจอื่นสำหรับการเขียนอาเรย์ numpy ไปยังไฟล์ PNG แต่สำหรับคนที่ไม่พอฉันเพิ่งวางnumpngwGitHub:

https://github.com/WarrenWeckesser/numpngw

และใน pypi: https://pypi.python.org/pypi/numpngw/

การพึ่งพาจากภายนอกเพียงอย่างเดียวคือจำนวนมาก

นี่คือตัวอย่างแรกจาก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


ฉันอยากรู้อยากเห็น lib ของคุณแตกต่างจากคนอื่น ๆ อย่างไร? เร็วขึ้นไหม มันมีคุณสมบัติแฟนซีหรือไม่?
F Lekschas

คุณสมบัติไม่กี่: (1) มันใช้อาร์เรย์ numpy (2) เขียนโดยใช้เพียง python และ numpy ดังนั้นจึงไม่จำเป็นต้องติดตั้งไลบรารี C (3) สามารถสร้างไฟล์ PNG แบบเคลื่อนไหวได้ (4) เป็นคลาสสำหรับการเขียนแอนิเมชั่น matplotlib เป็นไฟล์ PNG แบบเคลื่อนไหว
Warren Weckesser

ขอบคุณ! ฉันอยากรู้ว่ามันเปรียบเทียบกับstackoverflow.com/a/19174800/981933ในแง่ของประสิทธิภาพซึ่งเป็นไพ ธ อนบริสุทธิ์ได้อย่างไร วิธีการก่อนหน้านี้เร็วกว่า 2x กว่า PIL ซึ่งยอดเยี่ยมมาก ไม่เป็นไรถ้านั่นไม่ใช่เป้าหมายของคุณ :)
F Lekschas

2

สมมติว่าคุณต้องการภาพระดับสีเทา:

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

2

Imageioเป็นห้องสมุด Python ที่ให้อินเตอร์เฟซที่ใช้งานง่ายในการอ่านและเขียนข้อมูลรูปภาพที่หลากหลายรวมถึงภาพเคลื่อนไหววิดีโอข้อมูลปริมาตรและรูปแบบทางวิทยาศาสตร์ เป็นแพลตฟอร์มข้ามรันบน Python 2.7 และ 3.4+ และติดตั้งง่าย

นี่คือตัวอย่างสำหรับภาพระดับสีเทา:

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

หากคุณเกิดขึ้นกับการใช้งาน [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 ก็คือมันเป็นโซลูชันของงูหลามที่บริสุทธิ์ซึ่งทำให้สิ่งนี้มีน้ำหนักเบายิ่งขึ้น)


รุ่น 1.4 ออกมาแล้ว :-) (ฉันแก้ไขคำตอบแล้ว)
hans_meine

1

หากคุณกำลังทำงานในสภาพแวดล้อมของงูหลาม Spyder แล้วมันจะไม่ง่ายไปกว่าการคลิกขวาที่อาร์เรย์ในตัวสำรวจตัวแปรแล้วเลือกตัวเลือกแสดงภาพ

ป้อนคำอธิบายรูปภาพที่นี่

วิธีนี้จะขอให้คุณบันทึกภาพเป็น dsik ซึ่งส่วนใหญ่อยู่ในรูปแบบ PNG

ไม่จำเป็นต้องใช้ไลบรารี PIL ในกรณีนี้



0

สำหรับการบันทึกอาร์เรย์แบบ numpy เป็นอิมเมจคุณมีหลายทางเลือก:

1) อื่น ๆ ที่ดีที่สุด: 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) ...

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.