216 votes

Spécifier et enregistrer une figure avec une taille exacte en pixels

Disons que j'ai une image de 3841 x 7195 pixels. Je voudrais enregistrer le contenu de la figure sur le disque, ce qui donne une image de la taille de taille exacte Je spécifie en pixels.

Pas d'axe, pas de titres. Juste l'image. Personnellement, je ne me préoccupe pas des DPI, car je veux seulement spécifier la taille de l'image sur le disque à l'écran. en pixels .

J'ai lu autre fils Ils semblent tous effectuer des conversions en pouces, puis spécifier les dimensions de la figure en pouces et ajuster les ppp d'une manière ou d'une autre. J'aimerais éviter la perte potentielle de précision qui pourrait résulter des conversions de pixels en pouces.

J'ai essayé avec :

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)

sans succès (Python se plaint que la largeur et la hauteur doivent chacune être inférieures à 32768 ( ?))

D'après tout ce que j'ai vu, matplotlib exige que la taille de la figure soit spécifiée dans inches y dpi mais je ne suis intéressé que par les pixels la figure prend dans le disque. Comment puis-je faire cela ?

Pour clarifier : je cherche un moyen de faire cela avec matplotlib et non avec d'autres bibliothèques d'économie d'image.

2voto

codeslord Points 649

J'ai eu le même problème. J'ai utilisé PIL Image pour charger les images et les convertir en un tableau numpy puis j'ai tracé un rectangle en utilisant matplotlib. Il s'agissait d'une image jpg, il n'y avait donc aucun moyen pour moi d'obtenir le dpi à partir de PIL img.info['dpi'], donc la solution acceptée n'a pas fonctionné pour moi. Mais après quelques bricolages, j'ai trouvé le moyen d'enregistrer la figure avec la même taille que l'original.

J'ajoute la solution suivante ici en pensant qu'elle aidera quelqu'un qui a eu le même problème que le mien.

import matplotlib.pyplot as plt
from PIL import Image
import numpy as np

img = Image.open('my_image.jpg') #loading the image
image = np.array(img) #converting it to ndarray
dpi = plt.rcParams['figure.dpi'] #get the default dpi value
fig_size = (img.size[0]/dpi, img.size[1]/dpi) #saving the figure size
fig, ax = plt.subplots(1, figsize=fig_size) #applying figure size
#do whatver you want to do with the figure
fig.tight_layout() #just to be sure
fig.savefig('my_updated_image.jpg') #saving the image

Cela a permis d'enregistrer l'image avec la même résolution que l'image originale.

Si vous ne travaillez pas avec un notebook jupyter, vous pouvez obtenir le dpi de la manière suivante.

figure = plt.figure()
dpi = figure.dpi

2voto

Razorocean Points 147

Cette solution fonctionne pour les versions 3.0.1, 3.0.3 et 3.2.1 de matplotlib.

def save_inp_as_output(_img, c_name, dpi=100):
    h, w, _ = _img.shape
    fig, axes = plt.subplots(figsize=(h/dpi, w/dpi))
    fig.subplots_adjust(top=1.0, bottom=0, right=1.0, left=0, hspace=0, wspace=0) 
    axes.imshow(_img)
    axes.axis('off')
    plt.savefig(c_name, dpi=dpi, format='jpeg') 

Étant donné que le paramètre subplots_adjust fait en sorte que l'axe remplisse la figure, vous ne voulez pas spécifier un bbox_inches='tight', car cela crée en fait un remplissage d'espace blanc dans ce cas. Cette solution fonctionne également lorsque vous avez plus d'un sous-plot.

1voto

Sam-gege Points 70

Pourquoi tout le monde continue à utiliser matplotlib ?
Si votre image est un tableau numpy avec la forme (3841, 7195, 3), son type de données est numpy.uint8 et la valeur rgb va de 0 à 255, vous pouvez simplement enregistrer ce tableau comme une image sans utiliser matplotlib :

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

J'ai trouvé ce code dans un autre poste

-1voto

Alka Points 1

Plt.imsave a fonctionné pour moi. Vous pouvez trouver la documentation ici : https://matplotlib.org/3.2.1/api/_as_gen/matplotlib.pyplot.imsave.html

#file_path = directory address where the image will be stored along with file name and extension
#array = variable where the image is stored. I think for the original post this variable is im_np
plt.imsave(file_path, array)

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X