我有大量固定尺寸的图像(比如 500*500)。我想编写一个python脚本,将它们调整为固定大小(比如800 * 800),但会将原始图像保持在中心并用固定颜色(比如黑色)填充多余的区域。
我正在使用 PIL。我现在可以使用该resize
功能调整图像大小,但这会改变纵横比。有没有办法做到这一点?
我有大量固定尺寸的图像(比如 500*500)。我想编写一个python脚本,将它们调整为固定大小(比如800 * 800),但会将原始图像保持在中心并用固定颜色(比如黑色)填充多余的区域。
我正在使用 PIL。我现在可以使用该resize
功能调整图像大小,但这会改变纵横比。有没有办法做到这一点?
您可以创建具有所需新尺寸的新图像,并将旧图像粘贴到中心,然后保存。如果你愿意,你可以覆盖原始图像(你确定吗?;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')
就在这里。
做这样的事情:
from PIL import Image, ImageOps
ImageOps.expand(Image.open('original-image.png'),border=300,fill='black').save('imaged-with-border.png')
您可以在几行中编写相同的内容:
from PIL 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')
你说你有一个图像列表。然后你必须使用一个循环来处理所有这些:
from PIL 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)
或者,如果您使用的是OpenCV,它们有一个名为的函数copyMakeBorder
,允许您向图像的任何一侧添加填充。除了纯色之外,他们还为花哨的边框提供了一些很酷的选项,例如反射或扩展图像。
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)
PIL 的crop
方法实际上可以通过使用原始图像边界框之外的数字来为您处理这个问题,尽管文档中没有明确说明。left 和 top 的负数将为这些边缘添加黑色像素,而大于 right 和 bottom 的原始宽度和高度的数字将为这些边缘添加黑色像素。
此代码解释了奇数像素大小:
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))
代替 4 元组,您可以改为使用 2 元组在左/右和上/下添加相同数量的像素,或者使用 1 元组向所有侧添加相同数量的像素。
在这里考虑旧维度、新维度及其区别很重要。如果差异是奇数(不是偶数),则需要为左、上、右和下边框指定稍有不同的值。
假设旧维度是 ow,oh,新维度是 nw,nh。所以,这将是答案:
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')
您可以将图像加载scipy.misc.imread
为 numpy 数组。然后创建一个具有所需背景的数组,numpy.zeros((height, width, channels))
并将图像粘贴到所需位置:
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.
ximg = Image.open(qpath)
xwid,xhgt = func_ResizeImage(ximg)
qpanel_3 = tk.Frame(Body,width=xwid+10,height=xhgt+10,bg='white',bd=5)
ximg = ximg.resize((xwid,xhgt),Image.ANTIALIAS)
ximg = ImageTk.PhotoImage(ximg)
panel = tk.Label(qpanel_3,image=ximg)
panel.image = ximg
panel.grid(row = 2)