在python PIL中缩放和裁剪图像而不会超出图像尺寸

时间:2019-05-27 20:11:28

标签: python python-imaging-library crop image-scaling

我正在使用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 个答案:

答案 0 :(得分:1)

您应该计算作物的中心并在其上使用。 例如:

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)

具有宽度和高度值后,获取农作物的过程与上面相同。