37

如何在中心裁剪图像?因为我知道该框是定义左、上、右和下像素坐标的 4 元组,但我不知道如何获取这些坐标,所以它在中心裁剪。

4

7 回答 7

84

假设您知道要裁剪的尺寸(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))

如果您尝试将小图像裁剪得更大,这将中断,但我假设您不会尝试这样做(或者您可以抓住这种情况而不裁剪图像)。

于 2013-05-20T11:09:48.677 回答
13

所提出的解决方案的一个潜在问题是在所需尺寸和旧尺寸之间存在奇怪差异的情况下。每边不能有半个像素。必须选择一侧来放置额外的像素。

如果水平方向有奇数差异,下面的代码会将额外的像素放在右侧,如果垂直方向有奇数差异,则额外的像素会放在底部。

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
于 2015-09-03T21:38:51.557 回答
5

我觉得仍然缺少最适合大多数应用程序的最简单的解决方案。公认的答案存在像素不均匀的问题,尤其是对于 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))

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

在此处输入图像描述

后:

在此处输入图像描述

touples 显示尺寸。

于 2020-03-27T09:19:41.420 回答
2

这是我正在寻找的功能:

from PIL import Image
im = Image.open("test.jpg")

crop_rectangle = (50, 50, 200, 200)
cropped_im = im.crop(crop_rectangle)

cropped_im.show()

取自另一个答案

于 2017-08-12T08:01:57.407 回答
2

我最初使用了公认的答案:

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 提到的问题

所提出的解决方案的一个潜在问题是在所需尺寸和旧尺寸之间存在奇怪差异的情况下。每边不能有半个像素。必须选择一侧来放置额外的像素。

Dean Pospisil 的解决方案有效,我也想出了自己的计算来解决这个问题:

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))

使用接受的答案,180px x 180px要裁剪的图像180px x 101px将导致裁剪图像为180px x 102px

通过我的计算,它将被正确裁剪为180px x 101px

于 2020-05-22T05:55:05.520 回答
1

作物中心及周边:

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))
于 2019-12-17T21:24:54.000 回答
1

可能是我参加这个聚会迟到了,但至少我在这里 我想居中裁剪图像 将 9:16 图像转换为 16:9 纵向到横向

这是我使用的算法:

  1. 将图像分成 4 等份
  2. 丢弃第 1 部分和第 4 部分
  3. 将左设置为 0,右设置为图像的宽度

代码 :

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")

前 :

在此处输入图像描述

后:

在此处输入图像描述 我希望这有帮助

于 2020-06-28T23:39:08.357 回答