使用PIL在中心裁剪图像

use*_*069 19 python crop python-imaging-library

如何在中心裁剪图像?因为我知道盒子是一个定义左,上,右和下像素坐标的4元组,但我不知道如何获得这些坐标,所以它在中心作物.

Chr*_*rke 56

假设您知道要裁剪的尺寸(new_width X new_height):

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))
Run Code Online (Sandbox Code Playgroud)

如果您尝试裁剪较大的小图像,这将会中断,但我会假设您不会尝试(或者您可以捕捉到这种情况而不是裁剪图像).

  • 要注意的是,im.crop()不会就地裁剪图像,而是返回裁剪后的图像。因此,需要im = im.crop((left,top,right,bottom))。 (3认同)

小智 9

所提出的解决方案的一个潜在问题是在期望大小和旧大小之间存在奇怪差异的情况.你不能在每一边都有一个半像素.一个人必须选择一个侧面来放置一个额外的像素.

如果水平方向存在奇怪的差异,则下面的代码会将额外像素放在右侧,如果垂直方向存在奇数差异,则额外像素会向下移动.

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
Run Code Online (Sandbox Code Playgroud)

  • 舍入不正确,结果图像将不总是具有所需的尺寸.正确的公式是`right = width - floor((width - new_width)/ 2)` (4认同)

max*_*ond 6

我觉得仍然缺少最适合大多数应用程序的最简单的解决方案。公认的答案存在像素不均匀的问题,尤其是对于 ML 算法,裁剪图像的像素数至关重要。

在下面的示例中,我想从中心将图像裁剪为 224/100。我不在乎像素是否向左或向右移动 0.5,只要输出图片始终具有定义的尺寸即可。它避免了对数学的依赖。*。

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))
Run Code Online (Sandbox Code Playgroud)

输出是裁剪前的(代码中未显示):

在此输入图像描述

后:

在此输入图像描述

元组显示尺寸。