2012-06-21 30 views
16

Tengo una gran cantidad de imágenes de un tamaño fijo (digamos 500 * 500). Quiero escribir una secuencia de comandos python que los redimensionará a un tamaño fijo (digamos 800 * 800) pero mantendrá la imagen original en el centro y llenará el área excedente con un color fijo (por ejemplo, negro).Agregar bordes a una imagen usando python

Estoy usando PIL. Puedo cambiar el tamaño de la imagen usando la función resize ahora, pero eso cambia la relación de aspecto. ¿Hay alguna manera de hacer esto?

Respuesta

32

se puede crear una nueva imagen con el nuevo tamaño deseado, y pegar la imagen antigua en el centro, y luego guardarlo. Si lo desea, puede sobrescribir la imagen original (¿está seguro;? 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') 
22

Sí, la hay.

Hacer algo como esto:

import Image, ImageOps 
ImageOps.expand(Image.open('original-image.png'),border=300,fill='black').save('imaged-with-border.png') 

Usted puede escribir lo mismo en varias líneas:

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') 

Y usted decir que usted tiene una lista de imágenes. A continuación, debe utilizar un ciclo para procesar todos ellos:

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) 
+2

Interesante. ¿Sería posible elegir diferentes bordes para arriba-abajo e izquierda-derecha, por lo que el nuevo tamaño de imagen puede ser el parámetro, en lugar del tamaño del borde? – heltonbiker

+0

Gracias, ¿puedo diferenciar los valores x e y del borde ... algo así como decir (100,50)? –

+4

bien funcionó, 'ImageOps.expand (Image.open ('original-image.png'), border = (300,500), fill = 'black'). Save ('imaged-with-border.png') ' –

1

Es importante tener en cuenta la dimensión de edad, nueva dimensión y su diferencia aquí. Si la diferencia es impar (no uniforme), deberá especificar valores ligeramente diferentes para izquierda, arriba, derecha y bordes inferiores.

Supongamos que la dimensión anterior es ow, oh, y la nueva es nw, nh. Por lo tanto, esta sería la respuesta:

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') 
4

Alternativamente, si está utilizando OpenCV, tienen una función llamada copyMakeBorder que le permite agregar relleno a cualquiera de los lados de una imagen. Más allá de los colores sólidos, también tienen algunas opciones interesantes para bordes elegantes como reflejar o extender la imagen.

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) 

Example results of cv2.copyMakeBorder function

Fuentes: OpenCV border tutorial y OpenCV 3.1.0 Docs for copyMakeBorder

+3

Creo que deberías agregar 'cv2.BORDER_CONSTANT' antes de definir' value = color' como en http://docs.opencv.org/3.1.0/d3/df2/tutorial_py_basic_ops.html – gcucurull

1

método de PIL crop realidad puede manejar esto para usted mediante el uso de números que están fuera del cuadro delimitador de la imagen original, aunque no se indica explícitamente en the documentation. Los números negativos para la izquierda y la parte superior agregarán píxeles negros a esos bordes, mientras que los números mayores que el ancho y la altura originales para la derecha y la parte inferior agregarán píxeles negros a esos bordes.

Este código corresponde tamaños de píxeles impares:

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)) 

En lugar de la 4-tupla, en su lugar podría usar una 2-tupla para añadir el mismo número de píxeles a la izquierda/derecha y arriba/abajo , o una 1-tupla para agregar el mismo número de píxeles a todos los lados.

1

Puede cargar la imagen con scipy.misc.imread como una matriz numpy.A continuación, cree una matriz con el fondo deseado con numpy.zeros((height, width, channels)) y pegue la imagen en la ubicación deseada:

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. 
Cuestiones relacionadas