ChatGPT解决这个技术问题 Extra ChatGPT

如何使用 PIL 调整图像大小并保持其纵横比?

有没有明显的方法可以做到这一点,我错过了?我只是想制作缩略图。

由于这个问题很老但很有用,并且更喜欢枕头,因此对于基于枕头的教程,请看一下:pillow.readthedocs.org/en/latest/handbook/…
我创建了一个用于调整图像大小的小型库,它可以提供任何帮助:github.com/charlesthk/python-resize-image
PIL 的最后一个版本是在 2006 年。据我所知,枕头包是替代品。 Pillow 的最新版本是 2020 年 4 月 2 日。

o
oberbaum

定义最大尺寸。然后,通过取 min(maxwidth/width, maxheight/height) 计算调整大小比率。

正确的大小是 oldsize*ratio

当然还有一个库方法可以做到这一点:方法 Image.thumbnail
下面是来自 PIL documentation 的(已编辑)示例。

import os, sys
import Image

size = 128, 128

for infile in sys.argv[1:]:
    outfile = os.path.splitext(infile)[0] + ".thumbnail"
    if infile != outfile:
        try:
            im = Image.open(infile)
            im.thumbnail(size, Image.ANTIALIAS)
            im.save(outfile, "JPEG")
        except IOError:
            print "cannot create thumbnail for '%s'" % infile

就像它说的那样,该示例来自 pil 文档,并且该示例(仍然)不使用抗锯齿标志。不过,由于这可能是大多数人想要的,所以我添加了它。
@Eugene:试试 s= img.size(); ratio = MAXWIDTH/s[0]; newimg = img.resize((s[0]*ratio, s[1]*ratio), Image.ANTIALIAS) 之类的东西? (虽然这是浮点除法:)
请注意,PIL 的流行 Pillow 分支的用户不再首选 ANTIALIASpillow.readthedocs.org/en/3.0.x/releasenotes/…
Python 3 documentation for PIL 表示 thumbnail 仅在生成的图像小于原始图像时才有效。因此,我猜想使用 resize 是更好的方法。
默认情况下 PIL save() 方法质量较差,您可以使用 image.save(file_path, quality=quality_value) 更改质量。
r
rubo77

该脚本将使用 PIL (Python Imaging Library) 将图像 (somepic.jpg) 的大小调整为 300 像素的宽度和与新宽度成比例的高度。它通过确定 300 像素占原始宽度 (img.size[0]) 的百分比,然后将原始高度 (img.size[1]) 乘以该百分比来做到这一点。将“basewidth”更改为任何其他数字以更改图像的默认宽度。

from PIL import Image

basewidth = 300
img = Image.open('somepic.jpg')
wpercent = (basewidth/float(img.size[0]))
hsize = int((float(img.size[1])*float(wpercent)))
img = img.resize((basewidth,hsize), Image.ANTIALIAS)
img.save('somepic.jpg')

如果您在 Zope 中将此脚本用作外部方法,则需要“从 PIL 导入图像”行以避免名称空间与 Zope 的“图像”冲突。
此代码为我提供了一个 0 字节的输出文件 sompic.jpg。为什么会这样?我正在使用 Python 3.x
– 更新:Python 2.7 也是如此。
我可能已经想通了。如果要保存 .jpeg,请使用 img.save('sompic.jpg', 'JPEG')
nit:resize 没有 PIL.Image.ANTIALIAS 选项,实际上应该是 PIL.Image.LANCZOS,尽管它们的值都是 1,请参阅 pillow.readthedocs.io/en/3.1.x/reference/…
F
Franz

我还推荐使用 PIL 的缩略图方法,因为它消除了你所有的比例问题。

不过,一个重要提示是:替换

im.thumbnail(size)

im.thumbnail(size,Image.ANTIALIAS)

默认情况下,PIL 使用 Image.NEAREST 过滤器来调整大小,这会产生良好的性能,但质量很差。


这样,您只能减小图像的大小。无法使用 Image.thumbnail 增加大小。
m
muZk

基于@tomvon,我完成了以下使用(选择你的案例):

a) 调整高度(我知道新的宽度,所以我需要新的高度)

new_width  = 680
new_height = new_width * height / width 

b)调整宽度(我知道新的高度,所以我需要新的宽度)

new_height = 680
new_width  = new_height * width / height

然后只是:

img = img.resize((new_width, new_height), Image.ANTIALIAS)

你的变量都混在一起了。你的帖子说调整宽度,然后调整高度。在 resize 调用中,您将 new_width 用于高度和宽度?
建议修复该@Zachafer
更好地将它们转换为整数
出现错误:需要整数参数,得到浮点数
佚名

如果您试图保持相同的纵横比,那么您不会将大小调整为原始大小的某个百分比吗?

例如,原始大小的一半

half = 0.5
out = im.resize( [int(half * s) for s in im.size] )

可能是图像大小不一,需要调整大小的结果是统一大小的
这对我来说是一个非常简单而优雅的解决方案
很性感。此示例使用列表推导。使用生成器(用括号括起来)也可以:out = im.resize( (int(half * s) for s in im.size) )
如果您需要相对调整大小而不是特定的统一大小,则最简单的答案。如果您需要更大而不是更小,也易于更改。
可以进一步清理(整数除法):out = image.resize((s//2 for s in image.size))
B
BenT
from PIL import Image

img = Image.open('/your image path/image.jpg') # image extension *.png,*.jpg
new_width  = 200
new_height = 300
img = img.resize((new_width, new_height), Image.ANTIALIAS)
img.save('output image name.png') # format may what you want *.png, *jpg, *.gif

这不会保持源图像的纵横比。它将图像强制为 200x300,并导致图像被压缩或拉伸。
这并不能以任何方式回答这个问题。
op的错误答案。问题是“如何使用 PIL 调整图像大小并保持其纵横比?”
g
guettli
from PIL import Image
from resizeimage import resizeimage

def resize_file(in_file, out_file, size):
    with open(in_file) as fd:
        image = resizeimage.resize_thumbnail(Image.open(fd), size)
    image.save(out_file)
    image.close()

resize_file('foo.tif', 'foo_small.jpg', (256, 256))

我使用这个库:

pip install python-resize-image

可以只使用 PIL 中的 .thumbnail,您的解决方案不适用于增加大小,只是减小。
h
hoohoo-b

如果您不想/不需要使用 Pillow 打开图像,请使用以下命令:

from PIL import Image

new_img_arr = numpy.array(Image.fromarray(img_arr).resize((new_width, new_height), Image.ANTIALIAS))

V
Vito Gentile

如果您的调整大小限制仅在一个维度(宽度或高度)上,您可以将 PIL 的 Image.thumbnailsys.maxsize 结合使用。

例如,如果您想调整图像大小使其高度不超过 100 像素,同时保持纵横比,您可以执行以下操作:

import sys
from PIL import Image

image.thumbnail([sys.maxsize, 100], Image.ANTIALIAS)

请记住,Image.thumbnail 将调整图像的大小,这与 Image.resize 不同,它返回调整大小的图像而不更改原始图像。

编辑Image.ANTIALIAS 提出弃用警告,并将在 PIL 10(2023 年 7 月)中删除。相反,您应该使用 Resampling.LANCZOS

import sys
from PIL import Image
from PIL.Image import Resampling

image.thumbnail([sys.maxsize, 100], Resampling.LANCZOS)

S
Shanness

只是用更现代的包装器更新这个问题 这个库包装了 Pillow(PIL 的一个分支)https://pypi.org/project/python-resize-image/

允许你做这样的事情: -

from PIL import Image
from resizeimage import resizeimage

fd_img = open('test-image.jpeg', 'r')
img = Image.open(fd_img)
img = resizeimage.resize_width(img, 200)
img.save('test-image-width.jpeg', img.format)
fd_img.close()

在上面的链接中堆放更多示例。


resize_contain 看起来实际上非常有用!
R
RockOGOlic

我还将添加一个保持纵横比固定的调整大小版本。在这种情况下,它将根据初始纵横比 asp_rat(即浮点数(!))调整高度以匹配新图像的宽度。但是,要将宽度调整为高度,您只需在 else 循环中注释一行并取消注释另一行。你会看到,在哪里。

您不需要分号 (;),我保留它们只是为了提醒自己我经常使用的语言的语法。

from PIL import Image

img_path = "filename.png";
img = Image.open(img_path);     # puts our image to the buffer of the PIL.Image object

width, height = img.size;
asp_rat = width/height;

# Enter new width (in pixels)
new_width = 50;

# Enter new height (in pixels)
new_height = 54;

new_rat = new_width/new_height;

if (new_rat == asp_rat):
    img = img.resize((new_width, new_height), Image.ANTIALIAS); 

# adjusts the height to match the width
# NOTE: if you want to adjust the width to the height, instead -> 
# uncomment the second line (new_width) and comment the first one (new_height)
else:
    new_height = round(new_width / asp_rat);
    #new_width = round(new_height * asp_rat);
    img = img.resize((new_width, new_height), Image.ANTIALIAS);

# usage: resize((x,y), resample)
# resample filter -> PIL.Image.BILINEAR, PIL.Image.NEAREST (default), PIL.Image.BICUBIC, etc..
# https://pillow.readthedocs.io/en/3.1.x/reference/Image.html#PIL.Image.Image.resize

# Enter the name under which you would like to save the new image
img.save("outputname.png");

而且,它完成了。我试图尽可能多地记录它,所以很清楚。

我希望它可能对那里的人有所帮助!


n
noEmbryo

我试图为幻灯片视频调整一些图像的大小,因此,我想要的不仅仅是一个最大尺寸,而是一个最大宽度一个最大高度(视频帧的大小)。
并且总有可能制作纵向视频...
Image.thumbnail 方法很有前途,但我无法将其放大为较小的图像。

因此,在我在这里(或在其他一些地方)找不到明显的方法之后,我编写了这个函数并将其放在这里以供将来使用:

from PIL import Image

def get_resized_img(img_path, video_size):
    img = Image.open(img_path)
    width, height = video_size  # these are the MAX dimensions
    video_ratio = width / height
    img_ratio = img.size[0] / img.size[1]
    if video_ratio >= 1:  # the video is wide
        if img_ratio <= video_ratio:  # image is not wide enough
            width_new = int(height * img_ratio)
            size_new = width_new, height
        else:  # image is wider than video
            height_new = int(width / img_ratio)
            size_new = width, height_new
    else:  # the video is tall
        if img_ratio >= video_ratio:  # image is not tall enough
            height_new = int(width / img_ratio)
            size_new = width, height_new
        else:  # image is taller than video
            width_new = int(height * img_ratio)
            size_new = width_new, height
    return img.resize(size_new, resample=Image.LANCZOS)

K
Kanish Mathew

已通过“tomvon”更新了上面的答案

from PIL import Image

img = Image.open(image_path)

width, height = img.size[:2]

if height > width:
    baseheight = 64
    hpercent = (baseheight/float(img.size[1]))
    wsize = int((float(img.size[0])*float(hpercent)))
    img = img.resize((wsize, baseheight), Image.ANTIALIAS)
    img.save('resized.jpg')
else:
    basewidth = 64
    wpercent = (basewidth/float(img.size[0]))
    hsize = int((float(img.size[1])*float(wpercent)))
    img = img.resize((basewidth,hsize), Image.ANTIALIAS)
    img.save('resized.jpg')

这工作正常。我可以将其直接传递给画布或框架,而不是用新名称保存图像吗?
u
user391339

打开你的图像文件

from PIL import Image
im = Image.open("image.png")

Use PIL Image.resize(size, resample=0) method,您将图像的 (width, height) 替换为大小 2 元组。

这将以原始大小显示您的图像:

display(im.resize((int(im.size[0]),int(im.size[1])), 0) )

这将以 1/2 大小显示您的图像:

display(im.resize((int(im.size[0]/2),int(im.size[1]/2)), 0) )

这将以 1/3 大小显示您的图像:

display(im.resize((int(im.size[0]/3),int(im.size[1]/3)), 0) )

这将以 1/4 大小显示您的图像:

display(im.resize((int(im.size[0]/4),int(im.size[1]/4)), 0) )

等等等等


什么是 display(),它位于何处?
@Anthony,display() 是一个 iPython 函数,可以在 Jupyter Notebook 中用于显示图像。
A
Alex

一种保持受限比率并传递最大宽度/高度的简单方法。不是最漂亮的,但可以完成工作并且很容易理解:

def resize(img_path, max_px_size, output_folder):
    with Image.open(img_path) as img:
        width_0, height_0 = img.size
        out_f_name = os.path.split(img_path)[-1]
        out_f_path = os.path.join(output_folder, out_f_name)

        if max((width_0, height_0)) <= max_px_size:
            print('writing {} to disk (no change from original)'.format(out_f_path))
            img.save(out_f_path)
            return

        if width_0 > height_0:
            wpercent = max_px_size / float(width_0)
            hsize = int(float(height_0) * float(wpercent))
            img = img.resize((max_px_size, hsize), Image.ANTIALIAS)
            print('writing {} to disk'.format(out_f_path))
            img.save(out_f_path)
            return

        if width_0 < height_0:
            hpercent = max_px_size / float(height_0)
            wsize = int(float(width_0) * float(hpercent))
            img = img.resize((max_px_size, wsize), Image.ANTIALIAS)
            print('writing {} to disk'.format(out_f_path))
            img.save(out_f_path)
            return

这是使用此函数运行批量图像大小调整的 python script


R
Ruhul Amin

要使新图像的宽度和高度分别为原始图像的一半,请使用以下代码:

  from PIL import Image
  im = Image.open("image.jpg")
  resized_im = im.resize((round(im.size[0]*0.5), round(im.size[1]*0.5)))
    
  #Save the cropped image
  resized_im.save('resizedimage.jpg')

用固定宽度和比率调整大小:

from PIL import Image
new_width = 300
im = Image.open("img/7.jpeg")
concat = int(new_width/float(im.size[0]))
size = int((float(im.size[1])*float(concat)))
resized_im = im.resize((new_width,size), Image.ANTIALIAS)
#Save the cropped image
resized_im.save('resizedimage.jpg')

M
Mohamed TOUATI
# Importing Image class from PIL module
from PIL import Image

# Opens a image in RGB mode
im = Image.open(r"C:\Users\System-Pc\Desktop\ybear.jpg")

# Size of the image in pixels (size of original image)
# (This is not mandatory)
width, height = im.size

# Setting the points for cropped image
left = 4
top = height / 5
right = 154
bottom = 3 * height / 5

# Cropped image of above dimension
# (It will not change original image)
im1 = im.crop((left, top, right, bottom))
newsize = (300, 300)
im1 = im1.resize(newsize)
# Shows the image in image viewer
im1.show()

我喜欢 image.show()
N
Nips

我丑陋的例子。

函数获取文件,如:“pic[0-9a-z].[extension]”,将它们调整为 120x120,将部分移动到中心并保存到“ico[0-9a-z].[extension]”,适用于纵向和风景:

def imageResize(filepath):
    from PIL import Image
    file_dir=os.path.split(filepath)
    img = Image.open(filepath)

    if img.size[0] > img.size[1]:
        aspect = img.size[1]/120
        new_size = (img.size[0]/aspect, 120)
    else:
        aspect = img.size[0]/120
        new_size = (120, img.size[1]/aspect)
    img.resize(new_size).save(file_dir[0]+'/ico'+file_dir[1][3:])
    img = Image.open(file_dir[0]+'/ico'+file_dir[1][3:])

    if img.size[0] > img.size[1]:
        new_img = img.crop( (
            (((img.size[0])-120)/2),
            0,
            120+(((img.size[0])-120)/2),
            120
        ) )
    else:
        new_img = img.crop( (
            0,
            (((img.size[1])-120)/2),
            120,
            120+(((img.size[1])-120)/2)
        ) )

    new_img.save(file_dir[0]+'/ico'+file_dir[1][3:])

S
Sterling Archer

我以这种方式调整了图像的大小,并且效果很好

from io import BytesIO
from django.core.files.uploadedfile import InMemoryUploadedFile
import os, sys
from PIL import Image


def imageResize(image):
    outputIoStream = BytesIO()
    imageTemproaryResized = imageTemproary.resize( (1920,1080), Image.ANTIALIAS) 
    imageTemproaryResized.save(outputIoStream , format='PNG', quality='10') 
    outputIoStream.seek(0)
    uploadedImage = InMemoryUploadedFile(outputIoStream,'ImageField', "%s.jpg" % image.name.split('.')[0], 'image/jpeg', sys.getsizeof(outputIoStream), None)

    ## For upload local folder
    fs = FileSystemStorage()
    filename = fs.save(uploadedImage.name, uploadedImage)

m
mustafa candan

对我有用的最简单的方法

image = image.resize((image.width*2, image.height*2), Image.ANTIALIAS)

例子

from PIL import Image, ImageGrab
image = ImageGrab.grab(bbox=(0,0,400,600)) #take screenshot
image = image.resize((image.width*2, image.height*2), Image.ANTIALIAS)
image.save('Screen.png')

R
Riz.Khan

以下脚本创建了所有 JPEG 图像的精美缩略图,并保留了最大分辨率为 128x128 的纵横比。

from PIL import Image
img = Image.open("D:\\Pictures\\John.jpg")
img.thumbnail((680,680))
img.save("D:\\Pictures\\John_resize.jpg")

2
24_saurabh sharma
######get resize coordinate after resize the image using this function#####
def scale_img_pixel(points,original_dim,resize_dim):
        multi_list = [points]
        new_point_list = []
        multi_list_point = []
        for point in multi_list:
            multi_list_point.append([point[0],point[1]])
            multi_list_point.append([point[2],point[3]])
        for lsingle_point in multi_list_point:
            x1 = int((lsingle_point[0] * (resize_dim[0] / original_dim[0])))
            y1 = int((lsingle_point[1] * (resize_dim[1] / original_dim[1])))
            new_point_list.append(x1)
            new_point_list.append(y1)
            
        return new_point_list
    
    
    points = [774,265,909,409]
    original_dim = (1237,1036)
    resize_dim = (640,480)
    result = scale_img_pixel(points,original_dim,resize_dim)
    print("result: ", result)  

m
max
import cv2
from skimage import data 
import matplotlib.pyplot as plt
from skimage.util import img_as_ubyte
from skimage import io
filename='abc.png'
image=plt.imread(filename)
im=cv2.imread('abc.png')
print(im.shape)
im.resize(300,300)
print(im.shape)
plt.imshow(image)

不幸的是,这并没有回答这个问题,它明确地解决了库 PIL——而且它没有保持纵横比!。此外,您可以提供您的方法的分类描述来解释您的想法