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

有没有我忽略的明显的方法?我只是想做个缩略图。

1023732 次浏览

定义最大大小。 然后,通过取min(maxwidth/width, maxheight/height).

来计算调整大小的比率

合适的大小是oldsize*ratio

当然,还有一个库方法可以做到这一点:方法Image.thumbnail
下面是来自公益诉讼的文档.

. #的一个(编辑过的)示例
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.Resampling.LANCZOS)
im.save(outfile, "JPEG")
except IOError:
print "cannot create thumbnail for '%s'" % infile

如果你试图保持相同的纵横比,那么你不会调整原始大小的一些百分比吗?

例如,原来大小的一半

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

这个脚本将使用PIL (Python成像库)将图像(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.Resampling.LANCZOS)
img.save('somepic.jpg')

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

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

im.thumbnail(size)

im.thumbnail(size,Image.ANTIALIAS)

默认情况下,PIL使用映像。最近的过滤器调整大小,结果良好的性能,但质量差。

举个丑陋的例子。

函数获取像pic[0-9a-z]这样的文件。[扩展]",将它们调整为120x120,移动部分到中心,并保存到"ico[0-9a-z]。[扩展]”,肖像和风景作品:

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

基于@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)
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
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
只是用一个更现代的包装器更新了这个问题 这个图书馆包枕头(PIL的一个叉子) # EYZ0 < / p >

允许你这样做:-

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

在上面的链接中有更多的例子。

一个简单的方法,保持约束比率和通过最大宽度/高度。不是最漂亮的,但可以完成工作,而且很容易理解:

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脚本,它使用这个函数来运行批量图像调整。

如果你不想/不需要用Pillow打开图像,使用这个:

from PIL import Image


new_img_arr = numpy.array(Image.fromarray(img_arr).resize((new_width, new_height), Image.ANTIALIAS))
我试图为幻灯片视频调整一些图像的大小,因此,我想要的不仅仅是一个最大维度,而是一个最大宽度而且一个最大高度(视频帧的大小) 而且总有可能会有一个人像视频 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)

我用这种方法调整了图像的大小,效果很好

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)

已经更新了上面的答案“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')

打开图像文件

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

使用PIL Image。Resize (size, resample=0)方法,其中你替换(宽度,高度)你的图像的大小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) )

等等

我还将添加一个版本的调整大小,保持长宽比固定。 在本例中,它将根据初始宽高比asp_rat(即浮动(!))调整高度以匹配新图像的宽度。 但是,要根据高度调整宽度,只需在其他的循环中注释一行,取消注释另一行。你会看到。

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

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

这样就完成了。我尽我所能记录下来,所以很清楚。

我希望这对外面的人有所帮助!

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)

下面的脚本创建所有JPEG图像的漂亮缩略图,保留128x128最大分辨率的纵横比。

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

如果你的调整大小限制只有一个维度(宽度或高度),你可以结合PIL的Image.thumbnailsys.maxsize

例如,如果你想调整图像的大小,使其高度不超过100px,同时保持纵横比,你可以这样做:

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)

对我来说最简单的方法

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

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

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