在不超过图像尺寸的情况下以 python PIL 缩放和裁剪图像
Scale and crop an image in python PIL without exceeding the image dimensions
我正在使用 python PIL 裁剪图像。说我的形象是这样的:
这是我用于裁剪的简单代码片段:
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")
结果是:
我想在不超过图像尺寸的情况下缩小这个裁剪后的图像,保持纵横比(按比例的宽度和高度)不变,比如 20%,看起来像这样。
我应该如何缩小裁剪以保持宽高比同时不超过图像边界/尺寸?
您应该计算裁剪的中心并在那里使用它。
例如:
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) 点 w.r.t 您的原始图像。
在这种情况下,您将知道裁剪的最大宽度将是中心值和原始图像的外边界减去中心本身之间的 最小值:
im = Image.open("brad.jpg")
l = 200
t = 200
r = 300
b = 300
cropped = im.crop((l, t, r, b))
这给你:
如果你想从同一个中心开始将它“放大”到最大,那么你将有:
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))
结果给出,具有相同的中心:
编辑
如果您想保持纵横比,您应该在之前检索它(比例)并仅在结果尺寸仍适合原始图像时才应用裁剪。例如,如果你想放大 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)
获得宽度和高度值后,获取裁剪的过程与上述相同。
我正在使用 python PIL 裁剪图像。说我的形象是这样的:
这是我用于裁剪的简单代码片段:
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")
结果是:
我想在不超过图像尺寸的情况下缩小这个裁剪后的图像,保持纵横比(按比例的宽度和高度)不变,比如 20%,看起来像这样。
我应该如何缩小裁剪以保持宽高比同时不超过图像边界/尺寸?
您应该计算裁剪的中心并在那里使用它。 例如:
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) 点 w.r.t 您的原始图像。 在这种情况下,您将知道裁剪的最大宽度将是中心值和原始图像的外边界减去中心本身之间的 最小值:
im = Image.open("brad.jpg")
l = 200
t = 200
r = 300
b = 300
cropped = im.crop((l, t, r, b))
这给你:
如果你想从同一个中心开始将它“放大”到最大,那么你将有:
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))
结果给出,具有相同的中心:
编辑
如果您想保持纵横比,您应该在之前检索它(比例)并仅在结果尺寸仍适合原始图像时才应用裁剪。例如,如果你想放大 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)
获得宽度和高度值后,获取裁剪的过程与上述相同。