Python:图像调整大小:保持比例 - 添加白色背景

16

我想创建一个Python脚本来调整图像大小,但不改变其比例,只需添加白色背景。

(因此,一个500 * 700像素的图像将通过在每侧添加100像素的白色带将转换为700 * 700像素的图像)

我使用的三种图像类型是.PNG,.JPG和.GIF。我甚至不确定Gifs是否可行,PNG和JPG已经很棒了。

在我的情况下,它们必须是正方形。但如果有人能够使其适应任何比例,这将使看到该主题的最大人数受益,并且您将更加出色!

我看到了其他语言的相同主题,但没有Python,请问您知道如何做到这一点吗?

PS:我正在使用Python 3

我尝试过的:

组合三个图像。

如果我们以500 * 700像素的图像为例: 创建两个100 * 700px的白色图像,并将一个放在图像的每侧。受启发于:

使用Python水平组合多张图像

但是,我对Python有点陌生,也没有成功。


2
如果您将图像表示为2D numpy矩阵,则可以调用numpy例程来填充它们。 - cs95
SO不是一个代码编写服务。请发布您已经拥有的代码,并明确告诉我们您卡在哪个部分。如果您提供一个最小、完整和可验证的示例,那将是最好的。 - Mike Scotty
2
我建议创建一个所需大小的全白色图像,然后将您的输入图像居中粘贴到其中。毫无疑问,PIL模块可以完成这项工作。 - Błotosmętek
4个回答

27

终于做到了:

def Reformat_Image(ImageFilePath):

    from PIL import Image
    image = Image.open(ImageFilePath, 'r')
    image_size = image.size
    width = image_size[0]
    height = image_size[1]

    if(width != height):
        bigside = width if width > height else height

        background = Image.new('RGBA', (bigside, bigside), (255, 255, 255, 255))
        offset = (int(round(((bigside - width) / 2), 0)), int(round(((bigside - height) / 2),0)))

        background.paste(image, offset)
        background.save('out.png')
        print("Image has been resized !")

    else:
        print("Image is already a square, it has not been resized !")

感谢@Blotosmetek的建议,粘贴居中的图像比创建图像并将它们组合起来要简单得多!

PS:如果您还没有安装PIL,请使用pip安装库的名称为“pillow”,而不是PIL。但仍然在代码中使用它作为PIL。


嗨,刚看到这个问题,请问有人能告诉我如何使用这个来创建一个9:16的图像吗? - Nemanja
2
如果你想要透明而不是白色,将(255, 255, 255, 255)更改为(0, 0, 0, 0) - oruchkin

19

感谢@Jay D.,以下是更通用的版本:

from PIL import Image

def resize(image_pil, width, height):
    '''
    Resize PIL image keeping ratio and using white background.
    '''
    ratio_w = width / image_pil.width
    ratio_h = height / image_pil.height
    if ratio_w < ratio_h:
        # It must be fixed by width
        resize_width = width
        resize_height = round(ratio_w * image_pil.height)
    else:
        # Fixed by height
        resize_width = round(ratio_h * image_pil.width)
        resize_height = height
    image_resize = image_pil.resize((resize_width, resize_height), Image.ANTIALIAS)
    background = Image.new('RGBA', (width, height), (255, 255, 255, 255))
    offset = (round((width - resize_width) / 2), round((height - resize_height) / 2))
    background.paste(image_resize, offset)
    return background.convert('RGB')

1
真不错!比例调整做得很棒! - Eli O.
函数已更新,当图像不具有正方形比例时,我遇到了一个错误。 - estevo

1

这个被采纳的答案很好,我很高兴不用使用OpenCV。

正如@Nemanja提到的,如果你想让它适用于任何长宽比。这里是要使用的代码片段。我只是稍微修改了一下代码。

from PIL import Image

def Reformat_Image_With_Ratio(ImageFilePath, desired_aspect_ratio):
    
    image = Image.open(ImageFilePath, 'r')
    width = image.width
    height = image.height
    img_aspect_ratio = width/height
    
    if (img_aspect_ratio != desired_aspect_ratio):
        bigside = width if width > height else height
        other_side = int(bigside * desired_aspect_ratio)
        background = Image.new('RGBA', (other_side, bigside), (255, 0, 0, 255))
        offset = (int(round(((bigside - width) / 2), 0)), int(round(((bigside - height) / 2),0)))

        background.paste(image, offset)
        background.save('out4.png')
        print("Image has been resized !")

    else:
        print("Image is already a valid aspect ratio, it has not been resized !")

Reformat_Image_With_Ratio('test.png', 9/16)

0

另一个答案对我没用,我重写了它,这个可以用:

def resize_with_pad(im, target_width, target_height):
    '''
    Resize PIL image keeping ratio and using white background.
    '''
    target_ratio = target_height / target_width
    im_ratio = im.height / im.width
    if target_ratio > im_ratio:
        # It must be fixed by width
        resize_width = target_width
        resize_height = round(resize_width * im_ratio)
    else:
        # Fixed by height
        resize_height = target_height
        resize_width = round(resize_height / im_ratio)

    image_resize = im.resize((resize_width, resize_height), Image.ANTIALIAS)
    background = Image.new('RGBA', (target_width, target_height), (255, 255, 255, 255))
    offset = (round((target_width - resize_width) / 2), round((target_height - resize_height) / 2))
    background.paste(image_resize, offset)
    return background.convert('RGB')

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接