Как изменить размер изображения с помощью PIL и сохранить его соотношение сторон?
Есть ли очевидный способ сделать это, что я скучаю? Я просто пытаюсь сделать эскизы.
27 ответов
Определите максимальный размер. Затем вычислите коэффициент изменения размера, взяв 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
Этот скрипт изменит размер изображения (somepic.jpg) с помощью PIL (Python Imaging Library) до ширины 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('sompic.jpg')
Я также рекомендую использовать метод миниатюр PIL, потому что он удаляет все трудности отношения с вами.
Однако один важный совет: заменить
im.thumbnail(size)
с
im.thumbnail(size,Image.ANTIALIAS)
по умолчанию PIL использует фильтр Image.NEAREST для изменения размера, что приводит к хорошей производительности, но низкому качеству.
Основываясь на @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)
Если вы пытаетесь сохранить то же соотношение сторон, то не измените ли вы размер в процентах от исходного размера?
Например, половина оригинального размера
half = 0.5
out = im.resize( [int(half * s) for s in im.size] )
from PIL import Image
img = Image.open('/your iamge 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 u want ,*.png,*jpg,*.gif
PIL уже имеет возможность обрезать изображение
img = ImageOps.fit(img, size, Image.ANTIALIAS)
Вы можете комбинировать PIL с участием sys.maxsize
если ваш предел изменения размера установлен только в одном измерении (ширине или высоте).
Например, если вы хотите изменить размер изображения так, чтобы его высота была не более 100 пикселей, сохраняя при этом соотношение сторон, вы можете сделать что-то вроде этого:
import sys
from PIL import Image
image.thumbnail([sys.maxsize, 100], Image.ANTIALIAS)
Имейте в виду, что
Image.thumbnail
изменит размер изображения на месте, который отличается от
Image.resize
который вместо этого возвращает изображение с измененным размером без изменения исходного.
Если вы не хотите / не хотите открывать изображение с помощью Подушки, используйте это:
from PIL import Image
my_img = numpy.array(Image.fromarray(arr).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
Просто обновите этот вопрос более современной оболочкой. Эта библиотека обертывает 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()
Куча еще примеров в приведенной выше ссылке.
Откройте ваш файл изображения
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, которое имеет значение 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");
И это сделано. Я постарался задокументировать это как можно больше, чтобы было понятно.
Надеюсь, это может быть кому-то полезно!
Я пытался изменить размеры некоторых изображений для видео слайд-шоу, и поэтому я хотел не только одно максимальное измерение, но максимальную ширину и максимальную высоту (размер видеокадра).
И всегда была возможность портретного видео...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)
Обновили ответ "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')
Простой метод для сохранения ограниченных соотношений и передачи максимальной ширины / высоты. Не самая красивая, но выполняет свою работу и легко понять:
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, который использует эту функцию для запуска изменения размера изображения.
Я изменил размер изображения таким образом, и он работает очень хорошо
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)
Чтобы сделать новое изображение половиной ширины и половину высоты исходного изображения, используйте приведенный ниже код:
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()
Самый простой способ, который сработал для меня
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')
Мой безобразный пример.
Функция получает файл наподобие: "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:])
Следующий скрипт создает красивые эскизы всех изображений 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
def resize_height(img: Image.Image, height: int, resample=None):
"""resize by height, keep ratio."""
return img.resize((img.width * height // img.height, height), resample=resample)
def resize_width(img: Image.Image, width: int, resample=None):
"""resize by width, keep ratio."""
return img.resize((width, img.height * width // img.width), resample=resample)
######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)
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)
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))
Вы можете изменить размер изображения с помощью кода ниже:
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')