J'ai un grand nombre d'images de taille fixe (disons 500 * 500). Je veux écrire un script python qui les redimensionnera à une taille fixe (disons 800 * 800) mais gardera l'image d'origine au centre et remplira la zone excédentaire avec une couleur fixe (disons noir).
J'utilise PIL. Je peux maintenant redimensionner l'image en utilisant la fonction resize
maintenant, mais cela change le rapport d'aspect. Est-ce qu'il y a un moyen de faire ça?
Vous pouvez créer une nouvelle image avec la nouvelle taille souhaitée, coller l'ancienne image au centre, puis l'enregistrer. Si vous le souhaitez, vous pouvez remplacer l'image d'origine (êtes-vous sûr?; O)
import Image
old_im = Image.open('someimage.jpg')
old_size = old_im.size
new_size = (800, 800)
new_im = Image.new("RGB", new_size) ## luckily, this is already black!
new_im.paste(old_im, ((new_size[0]-old_size[0])/2,
(new_size[1]-old_size[1])/2))
new_im.show()
# new_im.save('someimage.jpg')
Oui il y a.
Faites quelque chose comme ça:
import Image, ImageOps
ImageOps.expand(Image.open('original-image.png'),border=300,fill='black').save('imaged-with-border.png')
Vous pouvez écrire la même chose sur plusieurs lignes:
import Image, ImageOps
img = Image.open('original-image.png')
img_with_border = ImageOps.expand(img,border=300,fill='black')
img_with_border.save('imaged-with-border.png')
Et vous dites que vous avez une liste d'images. Ensuite, vous devez utiliser un cycle pour les traiter tous:
import Image, ImageOps
for i in list-of-images:
img = Image.open(i)
img_with_border = ImageOps.expand(img,border=300,fill='black')
img_with_border.save('bordered-%s' % i)
Alternativement, si vous utilisez OpenCV , ils ont une fonction appelée copyMakeBorder
qui vous permet d'ajouter un remplissage à l'un des côtés d'une image. Au-delà des couleurs unies, ils ont également des options intéressantes pour les bordures fantaisie comme la réflexion ou l'extension de l'image.
import cv2
img = cv2.imread('image.jpg')
color = [101, 52, 152] # 'cause purple!
# border widths; I set them all to 150
top, bottom, left, right = [150]*4
img_with_border = cv2.copyMakeBorder(img, top, bottom, left, right, cv2.BORDER_CONSTANT, value=color)
Sources: Tutoriel sur les bordures OpenCV et Documents OpenCV 3.1.0 pour copyMakeBorder
La méthode crop
de PIL peut réellement gérer cela pour vous en utilisant des nombres qui se trouvent en dehors du cadre de délimitation de l'image d'origine, bien qu'elle ne soit pas explicitement indiquée dans la documentation . Les nombres négatifs pour la gauche et le haut ajouteront des pixels noirs à ces bords, tandis que les nombres supérieurs à la largeur et la hauteur d'origine pour la droite et le bas ajouteront des pixels noirs à ces bords.
Ce code tient compte des tailles de pixels impaires:
from PIL import Image
with Image.open('/path/to/image.gif') as im:
old_size = im.size
new_size = (800, 800)
if new_size > old_size:
# Set number of pixels to expand to the left, top, right,
# and bottom, making sure to account for even or odd numbers
if old_size[0] % 2 == 0:
add_left = add_right = (new_size[0] - old_size[0]) // 2
else:
add_left = (new_size[0] - old_size[0]) // 2
add_right = ((new_size[0] - old_size[0]) // 2) + 1
if old_size[1] % 2 == 0:
add_top = add_bottom = (new_size[1] - old_size[1]) // 2
else:
add_top = (new_size[1] - old_size[1]) // 2
add_bottom = ((new_size[1] - old_size[1]) // 2) + 1
left = 0 - add_left
top = 0 - add_top
right = old_size[0] + add_right
bottom = old_size[1] + add_bottom
# By default, the added pixels are black
im = im.crop((left, top, right, bottom))
Au lieu du 4-Tuple, vous pouvez utiliser à la place un 2-Tuple pour ajouter le même nombre de pixels à gauche/à droite et en haut/en bas, ou un 1-Tuple pour ajouter le même nombre de pixels à tous les côtés.
Vous pouvez charger l'image avec scipy.misc.imread
comme un tableau numpy. Ensuite, créez un tableau avec l'arrière-plan souhaité avec numpy.zeros((height, width, channels))
et collez l'image à l'emplacement souhaité:
import numpy as np
import scipy.misc
im = scipy.misc.imread('foo.jpg', mode='RGB')
height, width, channels = im.shape
# make canvas
im_bg = np.zeros((height, width, channels))
im_bg = (im_bg + 1) * 255 # e.g., make it white
# Your work: Compute where it should be
pad_left = ...
pad_top = ...
im_bg[pad_top:pad_top + height,
pad_left:pad_left + width,
:] = im
# im_bg is now the image with the background.
Il est important de considérer l'ancienne dimension, la nouvelle dimension et leur différence ici. Si la différence est impaire (pas même), vous devrez spécifier des valeurs légèrement différentes pour les bordures gauche, haut, droite et bas.
Supposons que l'ancienne dimension est ow, oh et la nouvelle est nw, nh. Donc, ce serait la réponse:
import Image, ImageOps
img = Image.open('original-image.png')
deltaw=nw-ow
deltah=nh-oh
ltrb_border=(deltaw/2,deltah/2,deltaw-(deltaw/2),deltah-(deltah/2))
img_with_border = ImageOps.expand(img,border=ltrb_border,fill='black')
img_with_border.save('imaged-with-border.png')