Especificar y guardar una figura con el tamaño exacto en píxeles

Digamos que tengo una imagen de tamaño 3841 x 7195 píxeles. Me gustaría guardar el contenido de la figura en el disco, dando como resultado una imagen del tamaño exacto que especifico en píxeles.

Sin eje, sin títulos. Solo la imagen. No me interesan personalmente los DPI, ya que solo quiero especificar el tamaño que toma la imagen en píxeles en la pantalla.

He leído otros hilos , y todos parecen hacer conversiones a pulgadas y luego especifican las dimensiones de la figura en pulgadas y ajustan los dpi de alguna manera. Me gustaría evitar lidiar con la posible pérdida de precisión que podría resultar de las conversiones de píxel a pulgadas.

Lo he intentado con:

w = 7195 h = 3841 fig = plt.figure(frameon=False) fig.set_size_inches(w,h) ax = plt.Axes(fig, [0., 0., 1., 1.]) ax.set_axis_off() fig.add_axes(ax) ax.imshow(im_np, aspect='normal') fig.savefig(some_path, dpi=1) 

sin suerte (Python se queja de que el ancho y la altura deben estar por debajo de 32768 (?))

Por todo lo que he visto, matplotlib requiere que el tamaño de la figura se especifique en inches y dpi , pero solo me interesan los píxeles que la figura toma en el disco. ¿Cómo puedo hacer esto?

Para aclarar: estoy buscando una manera de hacer esto con matplotlib , y no con otras bibliotecas para guardar imágenes.

Matplotlib no funciona con píxeles directamente, sino con tamaños físicos y DPI. Si desea mostrar una figura con un tamaño de píxel determinado, necesita conocer el DPI de su monitor. Por ejemplo, este enlace lo detectará por ti.

Si tiene una imagen de 3841×7195 píxeles, es poco probable que su monitor sea tan grande, por lo que no podrá mostrar una figura de ese tamaño (matplotlib requiere que la figura se ajuste a la pantalla, si solicita un tamaño demasiado grande se reducirá al tamaño de la pantalla). Imaginemos que desea una imagen de 800×800 píxeles solo como ejemplo. Aquí le mostramos cómo mostrar una imagen de 800×800 píxeles en mi monitor ( my_dpi=96 ):

 plt.figure(figsize=(800/my_dpi, 800/my_dpi), dpi=my_dpi) 

Así que básicamente solo divides las dimensiones en pulgadas por tu DPI.

Si desea guardar una figura de un tamaño específico, entonces es un asunto diferente. Los DPI de pantalla ya no son tan importantes (a menos que solicite una figura que no se ajuste a la pantalla). Usando el mismo ejemplo de la figura de 800×800 píxeles, podemos guardarlo en diferentes resoluciones usando la palabra clave dpi de savefig . Para guardarlo en la misma resolución que la pantalla, use los mismos ppp:

 plt.savefig('my_fig.png', dpi=my_dpi) 

Para guardarlo como una imagen de 8000×8000 píxeles, use un dpi 10 veces más grande:

 plt.savefig('my_fig.png', dpi=my_dpi * 10) 

Tenga en cuenta que la configuración de la DPI no es compatible con todos los backends. Aquí, se utiliza el backend PNG, pero los backends pdf y ps implementarán el tamaño de manera diferente. Además, cambiar el DPI y los tamaños también afectará cosas como el tamaño de fuente. Un DPI más grande mantendrá los mismos tamaños relativos de fonts y elementos, pero si desea fonts más pequeñas para una figura más grande, necesita boost el tamaño físico en lugar del DPI.

Volviendo a su ejemplo, si desea guardar una imagen con 3841 x 7195 píxeles, podría hacer lo siguiente:

 plt.figure(figsize=(3.841, 7.195), dpi=100) ( your code ...) plt.savefig('myfig.png', dpi=1000) 

Tenga en cuenta que utilicé la cifra de ppp de 100 para ajustar en la mayoría de las pantallas, pero la guardé con dpi=1000 para lograr la resolución requerida. En mi sistema, esto produce un png con 3840×7190 píxeles. Parece que el DPI guardado es siempre 0,02 píxeles / pulgada más pequeño que el valor seleccionado, lo que tendrá un efecto (pequeño) en los tamaños de imagen grandes. Un poco más de discusión de esto aquí .

Esto funcionó para mí, según su código, generando una imagen png de 93Mb con ruido de color y las dimensiones deseadas:

 import matplotlib.pyplot as plt import numpy w = 7195 h = 3841 im_np = numpy.random.rand(h, w) fig = plt.figure(frameon=False) fig.set_size_inches(w,h) ax = plt.Axes(fig, [0., 0., 1., 1.]) ax.set_axis_off() fig.add_axes(ax) ax.imshow(im_np, aspect='normal') fig.savefig('figure.png', dpi=1) 

Estoy usando las últimas versiones PIP de las bibliotecas de Python 2.7 en Linux Mint 13.

¡Espero que ayude!

De acuerdo con la respuesta aceptada por tiago, aquí hay una pequeña función genérica que exporta una matriz numpy a una imagen que tiene la misma resolución que la matriz:

 import matplotlib.pyplot as plt import numpy as np def export_figure_matplotlib(arr, f_name, dpi=200, resize_fact=1, plt_show=False): """ Export array as figure in original resolution :param arr: array of image to save in original resolution :param f_name: name of file where to save figure :param resize_fact: resize facter wrt shape of arr, in (0, np.infty) :param dpi: dpi of your screen :param plt_show: show plot or not """ fig = plt.figure(frameon=False) fig.set_size_inches(arr.shape[1]/dpi, arr.shape[0]/dpi) ax = plt.Axes(fig, [0., 0., 1., 1.]) ax.set_axis_off() fig.add_axes(ax) ax.imshow(arr) plt.savefig(f_name, dpi=(dpi * resize_fact)) if plt_show: plt.show() else: plt.close() 

Como se dijo en la respuesta anterior de tiago, la pantalla DPI debe encontrarse primero, lo que se puede hacer aquí, por ejemplo: http://dpi.lv

He agregado un argumento adicional resize_fact en la función que puede exportar la imagen al 50% (0,5) de la resolución original, por ejemplo.