python - procesamiento - Guardar una matriz Numpy como una imagen
matrices en python numpy (13)
Addendum a la respuesta de @ 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()
Entonces puedes hacer:
saveAsPNG([[0xffFF0000, 0xffFFFF00],
[0xff00aa77, 0xff333333]], ''test_grid.png'')
Produciendo test_grid.png
:
(La transparencia también funciona, al reducir el byte alto de 0xff
).
Tengo una matriz en el tipo de una matriz Numpy. ¿Cómo lo escribiría en el disco como una imagen? Cualquier formato funciona (png, jpeg, bmp ...). Una restricción importante es que PIL no está presente.
Con matplotlib
:
import matplotlib
matplotlib.image.imsave(''name.png'', array)
Funciona con matplotlib 1.3.1, no sé acerca de la versión más baja. Desde el 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.
El mundo probablemente no necesite otro paquete para escribir una matriz numpy en un archivo PNG, pero para aquellos que no pueden obtener suficiente, recientemente puse numpngw
en github:
https://github.com/WarrenWeckesser/numpngw
y en pypi: https://pypi.python.org/pypi/numpngw/
La única dependencia externa es numpy.
Aquí está el primer ejemplo del directorio de examples
del repositorio. La línea esencial es simplemente
write_png(''example1.png'', img)
donde img
es una matriz numpy. Todo el código anterior a esa línea es instrucciones de importación y código para crear 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)
Aquí está el archivo PNG que crea:
Esto usa PIL, pero tal vez algunos lo encuentren útil:
import scipy.misc
scipy.misc.imsave(''outfile.jpg'', image_array)
EDITAR : La versión scipy
actual comenzó a normalizar todas las imágenes para que min (data) se convirtiera en negro y max (data) se volviera blanco. Esto no es deseado si los datos deben ser niveles de gris exactos o canales RGB exactos. La solución:
import scipy.misc
scipy.misc.toimage(image_array, cmin=0.0, cmax=...).save(''outfile.jpg'')
Hay opencv
para python ( http://docs.opencv.org/trunk/doc/py_tutorials/py_tutorials.html ).
import cv2
import numpy as np
cv2.imwrite("filename.png", np.zeros((10,10)))
útil si necesita hacer más procesamiento que no sea guardar.
Puede usar la biblioteca ''skimage'' en Python
Ejemplo:
from skimage.io import imsave
imsave(''Path_to_your_folder/File_name.jpg'',your_array)
Pure Python (2 y 3), un fragmento sin dependencias de terceros.
Esta función escribe RGBA
PNG comprimido, de verdadero color (4 bytes por píxel).
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'''')])
... Los datos deben escribirse directamente en un archivo abierto como binario, como en:
data = write_png(buf, 64, 64)
with open("my_image.png", ''wb'') as fd:
fd.write(data)
- Fuente original
- Ver también: Rust Port de esta pregunta.
- Ejemplo de uso gracias a @Evgeni Sergeev: https://.com/a/21034111/432509
Si ya usa [Py] Qt, puede que le interese qimage2ndarray . Comenzando con la versión 1.4 (recién lanzado), PySide también es compatible, y habrá una pequeña función imsave(filename, array)
similar a la de scipy, pero usando Qt en lugar de PIL. Con 1.3, solo usa algo como lo siguiente:
qImage = array2qimage(image, normalize = False) # create QImage from ndarray
success = qImage.save(filename) # use Qt''s image IO functions for saving PNG/JPG/..
(Otra ventaja de 1.4 es que es una solución pura de python, lo que hace que sea aún más ligero).
Suponiendo que quiere una imagen en escala de grises:
im = Image.new(''L'', (width, height))
im.putdata(an_array.flatten().tolist())
im.save("image.tiff")
matplotlib svn tiene una nueva función para guardar imágenes como solo una imagen, sin ejes, etc. También es una función muy simple de respaldar, si no quieres instalar svn (copiado directamente desde image.py en matplotlib svn, quitado el docstring por brevedad):
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)