Масштабирование и обрезка изображения в Python PIL без превышения размеров изображения - PullRequest
0 голосов
/ 27 мая 2019

Я обрезаю изображение с помощью Python PIL. Скажи, что мое изображение таково:

enter image description here

Это простой фрагмент кода, который я использую для кадрирования:

from PIL import Image
im = Image.open(image)
cropped_image = im.crop((topLeft_x, topLeft_y, bottomRight_x, bottomRight_y))
cropped_image.save("Out.jpg")

Результат этого:

enter image description here

Я хочу масштабировать это обрезанное изображение, сохраняя пропорции (пропорциональные ширину и высоту), скажем, 20%, чтобы выглядеть примерно так, не превышая размеров изображения.

enter image description here

Как мне масштабировать кадрирование таким образом, чтобы соотношение сторон сохранялось, не превышая границу / размеры изображения?

1 Ответ

1 голос
/ 27 мая 2019

Вы должны рассчитать центр вашего урожая и использовать его там.Например:

crop_width = right - left
crop_height = bottom - top
crop_center_x = int(left + crop_width/2)
crop_center_y = (top + crop_height/2)

Таким образом, вы получите точку (x, y), которая соответствует центру вашего урожая по сравнению с вашим исходным изображением.В этом случае вы будете знать, что максимальная ширина для вашей обрезки будет минимум между значением центра и внешними границами исходного изображения минус сам центр:

im = Image.open("brad.jpg")
l = 200
t = 200
r = 300
b = 300
cropped = im.crop((l, t, r, b))

Что дает вам:

enter image description here

Если вы хотите «увеличить» его до максимума, начиная с того же центра, то у вас будет:

max_width = min(crop_center_x, im.size[0]-crop_center_x)
max_height = min(crop_center_y, im.size[1]-crop_center_y)
new_l = crop_center_x - max_width
new_t = crop_center_x - max_height
new_r = crop_center_x + max_width
new_b = crop_center_x + max_height
new_crop = im.crop((new_l, new_t, new_r, new_b))

, что в результате дает тот же центр:

enter image description here


Редактировать

Если выЕсли вы хотите сохранить соотношение сторон, вы должны восстановить его (соотношение) и применять обрезку только в том случае, если полученный размер все еще будет соответствовать исходному изображению.Например, если вы хотите увеличить его на 20%:

ratio = crop_height/crop_width
scale = 20/100
new_width = int(crop_width + (crop_width*scale))

# Here we are using the previously calculated value for max_width to 
# determine if the new one would be too large.
# Note that the width that we calculated here (new_width) refers to both
# sides of the crop, while the max_width calculated previously refers to
# one side only; same for height. Sorry for the confusion.
if max_width < new_width/2:
    new_width = int(2*max_width)

new_height = int(new_width*ratio)

# Do the same for the height, update width if necessary
if max_height < new_height/2:
    new_height = int(2*max_height)
    new_width = int(new_height/ratio)

adjusted_scale = (new_width - crop_width)/crop_width

if adjusted_scale != scale:
    print("Scale adjusted to: {:.2f}".format(adjusted_scale))

new_l = int(crop_center_x - new_width/2)
new_r = int(crop_center_x + new_width/2)
new_t = int(crop_center_y - new_height/2)
new_b = int(crop_center_y + new_height/2)

Когда у вас есть значения ширины и высоты, процесс получения обрезки такой же, как и выше.

...