Crop an image in the centre using PIL
如何在中央裁剪图像? 因为我知道该框是一个四元组,定义了左,上,右和下像素坐标,但我不知道如何获取这些坐标,因此它会在中心裁剪。
假设您知道要裁剪的大小(new_width X new_height):
1 2 3 4 5 6 7 8 9 10 11 | import Image im = Image.open(<your image>) width, height = im.size # Get dimensions left = (width - new_width)/2 top = (height - new_height)/2 right = (width + new_width)/2 bottom = (height + new_height)/2 # Crop the center of the image im = im.crop((left, top, right, bottom)) |
如果您尝试裁切较大的小图像,这将中断,但我将假定您不会尝试这样做(或者您可以捕获这种情况而不裁切图像)。
所提出的解决方案的一个潜在问题是在所需尺寸和旧尺寸之间存在奇数差异的情况。每边不能有半个像素。一个人必须选择一侧以放置一个额外的像素。
如果水平方向存在奇数差异,则下面的代码会将多余的像素放在右边,如果垂直方向存在奇数差异,则多余的像素会移到底部。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | import numpy as np def center_crop(img, new_width=None, new_height=None): width = img.shape[1] height = img.shape[0] if new_width is None: new_width = min(width, height) if new_height is None: new_height = min(width, height) left = int(np.ceil((width - new_width) / 2)) right = width - int(np.floor((width - new_width) / 2)) top = int(np.ceil((height - new_height) / 2)) bottom = height - int(np.floor((height - new_height) / 2)) if len(img.shape) == 2: center_cropped_img = img[top:bottom, left:right] else: center_cropped_img = img[top:bottom, left:right, ...] return center_cropped_img |
这是我一直在寻找的功能:
1 2 3 4 5 6 7 | from PIL import Image im = Image.open("test.jpg") crop_rectangle = (50, 50, 200, 200) cropped_im = im.crop(crop_rectangle) cropped_im.show() |
取自另一个答案
我觉得最适合大多数应用程序的最简单解决方案仍然缺失。公认的答案存在像素不均匀的问题,尤其是对于ML算法而言,裁剪图像的像素数至关重要。
在下面的示例中,我想从中心将图像裁剪为224/100。我不在乎像素是否向左或向右移动0.5,只要输出图片始终具有定义的尺寸即可。它避免了对数学的依赖。
1 2 3 4 5 6 7 8 9 10 11 12 13 | from PIL import Image import matplotlib.pyplot as plt im = Image.open("test.jpg") left = int(im.size[0]/2-224/2) upper = int(im.size[1]/2-100/2) right = left +224 lower = upper + 100 im_cropped = im.crop((left, upper,right,lower)) print(im_cropped.size) plt.imshow(np.asarray(im_cropped)) |
输出在裁剪之前(未在代码中显示):
后:
阴影显示尺寸。
可能我参加这个聚会迟到了,但至少我在这里
我想对图像进行中心裁剪将9:16图像转换为16:9肖像以横向
这是我使用的算法:
代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 | from PIL import Image im = Image.open('main.jpg') width, height = im.size if height > width: h2 = height/2 h4 = h2/2 border = (0, h4, width, h4*3) cropped_img = im.crop(border) cropped_img.save("test.jpg") |
之前:
后:

我希望这有帮助
我最初使用公认的答案:
1 2 3 4 5 6 7 8 9 10 11 | import Image im = Image.open(<your image>) width, height = im.size # Get dimensions left = (width - new_width)/2 top = (height - new_height)/2 right = (width + new_width)/2 bottom = (height + new_height)/2 # Crop the center of the image im = im.crop((left, top, right, bottom)) |
但是我遇到了Dean Pospisil提到的问题
One potential problem with the proposed solution is in the case there
is an odd difference between the desired size, and old size. You can't
have a half pixel on each side. One has to choose a side to put an
extra pixel on.
Dean Pospisil的解决方案有效,我还想出了自己的解决方案:
1 2 3 4 5 6 7 8 9 10 11 12 13 | import Image im = Image.open(<your image>) width, height = im.size # Get dimensions left = round((width - new_width)/2) top = round((height - new_height)/2) x_right = round(width - new_width) - left x_bottom = round(height - new_height) - top right = width - x_right bottom = height - x_bottom # Crop the center of the image im = im.crop((left, top, right, bottom)) |
有了接受的答案,要裁剪为
根据我的计算,它将正确裁剪为
作物中心及其周围:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | def im_crop_around(img, xc, yc, w, h): img_width, img_height = img.size # Get dimensions left, right = xc - w / 2, xc + w / 2 top, bottom = yc - h / 2, yc + h / 2 left, top = round(max(0, left)), round(max(0, top)) right, bottom = round(min(img_width - 0, right)), round(min(img_height - 0, bottom)) return img.crop((left, top, right, bottom)) def im_crop_center(img, w, h): img_width, img_height = img.size left, right = (img_width - w) / 2, (img_width + w) / 2 top, bottom = (img_height - h) / 2, (img_height + h) / 2 left, top = round(max(0, left)), round(max(0, top)) right, bottom = round(min(img_width - 0, right)), round(min(img_height - 0, bottom)) return img.crop((left, top, right, bottom)) |