Есть ли очевидный способ сделать это, который мне не хватает? Я просто пытаюсь сделать миниатюры.
Как изменить размер изображения с помощью PIL и сохранить его соотношение сторон?
Ответы (21)
Определите максимальный размер. Затем вычислите коэффициент изменения размера, взяв min(maxwidth/width, maxheight/height)
.
Правильный размер oldsize*ratio
.
Конечно, существует также библиотечный метод для этого: метод Image.thumbnail
.
Ниже приведен (отредактированный) пример из документация PIL.
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
s= img.size(); ratio = MAXWIDTH/s[0]; newimg = img.resize((s[0]*ratio, s[1]*ratio), Image.ANTIALIAS)
? (хотя это для деления с плавающей запятой :)
- person gnud; 13.12.2012
ANTIALIAS
больше не является предпочтительным для пользователей популярной вилки Pillow PIL. Pillow.readthedocs.org/ ru / 3.0.x / releasenotes /
- person Joshmaker; 23.12.2015
thumbnail
работает, только если итоговое изображение меньше исходного. Из-за этого я бы предположил, что использование resize
- лучший способ.
- person So S; 29.01.2017
save()
имеет низкое качество, вы можете использовать image.save(file_path, quality=quality_value)
, чтобы изменить качество.
- person codezjx; 21.10.2017
Image.crop
- Pillow.readthedocs.io/en/3.1.x/reference/
- person gnud; 10.05.2018
In Pillow 2.5 the default filter for thumbnail() was changed from NEAREST to ANTIALIAS
- person pnd; 28.06.2018
Этот скрипт изменит размер изображения (somepic.jpg) с помощью PIL (Python Imaging Library) до ширины 300 пикселей и высоты, пропорциональной новой ширине. Для этого он определяет, какой процент от исходной ширины составляет 300 пикселей (img.size [0]), а затем умножает исходную высоту (img.size [1]) на этот процент. Измените базовую ширину на любое другое число, чтобы изменить ширину изображений по умолчанию.
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')
sompic.jpg
. Почему это происходит? Я использую Python 3.x
- person imrek; 26.03.2017
.jpeg
, используйте img.save('sompic.jpg', 'JPEG')
.
- person imrek; 26.03.2017
PIL.Image.ANTIALIAS
для resize
, на самом деле должно быть PIL.Image.LANCZOS
, хотя они оба 1
по значению, см. Pillow.readthedocs.io/en/3.1.x/reference/
- person Fred Wu; 02.05.2017
PIL.Image.ANTIALIAS
находится в PIL версии 1.1.7. Это идет с Anaconda3 v5.x
- person J'e; 07.06.2018
Я также рекомендую использовать метод эскизов PIL, потому что он избавляет вас от всех проблем с соотношением сторон.
Однако один важный совет: замените
im.thumbnail(size)
с участием
im.thumbnail(size,Image.ANTIALIAS)
по умолчанию PIL использует фильтр Image.NEAREST для изменения размера, что приводит к хорошей производительности, но низкому качеству.
Image.thumbnail
.
- person burny; 01.10.2019
Основываясь на @tomvon, я закончил использовать следующее (выберите свой случай):
а) Изменение высоты (Я знаю новую ширину, поэтому мне нужна новая высота)
new_width = 680
new_height = new_width * height / width
б) Изменение ширины (Я знаю новую высоту, поэтому мне нужна новая ширина)
new_height = 680
new_width = new_height * width / height
Тогда просто:
img = img.resize((new_width, new_height), Image.ANTIALIAS)
resize
вы используете new_width
как для высоты, так и для ширины?
- person Zachafer; 20.01.2016
Если вы пытаетесь сохранить такое же соотношение сторон, разве вы не измените размер на какой-то процент от исходного размера?
Например, половина оригинального размера
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) )
- person howdoicode; 07.11.2020
PIL уже имеет возможность обрезать изображение
img = ImageOps.fit(img, size, 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
Если вы не хотите / вам не нужно открывать изображение с помощью Pillow, используйте это:
from PIL import Image
new_img_arr = numpy.array(Image.fromarray(img_arr).resize((new_width, new_height), Image.ANTIALIAS))
Просто обновите этот вопрос с помощью более современной оболочки Эта библиотека обертывает 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()
Кучи больше примеров в приведенной выше ссылке.
Я пытался изменить размер некоторых изображений для видео слайд-шоу, и из-за этого мне нужен был не только один максимальный размер, но и максимальная ширина и максимальная высота (размер видеокадра).
И всегда была возможность сделать портретное видео ...
Метод 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 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) )
и т. д. и т. д.
display()
и где он находится?
- person Anthony; 11.05.2020
display()
- это функция iPython, которую можно использовать в Jupyter Notebook для отображения изображений.
- person Qinjie; 09.07.2020
Я также добавлю версию изменения размера, которая сохраняет фиксированное соотношение сторон. В этом случае он отрегулирует высоту в соответствии с шириной нового изображения на основе исходного соотношения сторон, asp_rat, которое равно float (!). Но вместо этого, чтобы настроить ширину на высоту, вам просто нужно прокомментировать одну строку и раскомментировать другую в цикле 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");
И это сделано. Я старался задокументировать это как можно больше, чтобы было понятно.
Надеюсь, это может быть кому-то полезно!
Простой метод сохранения ограниченных соотношений и передачи максимальной ширины / высоты. Не самый красивый, но выполняет свою работу и его легко понять:
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, который использует эту функцию для запуска пакетного изменения размера изображения.
Обновили ответ "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')
Вы можете комбинировать Image.thumbnail
PIL с sys.maxsize
, если ограничение на изменение размера задано только для одного измерения (ширины или высоты).
Например, если вы хотите изменить размер изображения так, чтобы его высота была не более 100 пикселей, сохраняя при этом соотношение сторон, вы можете сделать что-то вроде этого:
import sys
from PIL import Image
image.thumbnail([sys.maxsize, 100], Image.ANTIALIAS)
Имейте в виду, что Image.thumbnail
изменит размер изображения на месте, в отличие от Image.resize
, который вместо этого возвращает изображение с измененным размером без изменения исходного.
Мой некрасивый пример.
Функция получает файл типа: «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:])
Я изменил размер изображения таким образом, и оно работает очень хорошо
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)
Следующий скрипт создает красивые эскизы всех изображений JPEG с сохранением соотношений сторон с максимальным разрешением 128x128.
from PIL import Image
img = Image.open("D:\\Pictures\\John.jpg")
img.thumbnail((680,680))
img.save("D:\\Pictures\\John_resize.jpg")
Вы можете изменить размер изображения с помощью кода ниже:
From PIL import Image
img=Image.open('Filename.jpg') # paste image in python folder
print(img.size())
new_img=img.resize((400,400))
new_img.save('new_filename.jpg')