如何在中心裁剪图像?因为我知道盒子是一个定义左,上,右和下像素坐标的4元组,但我不知道如何获得这些坐标,所以它在中心作物。
答案 0 :(得分:48)
假设您知道要裁剪的尺寸(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
im.crop((left, top, right, bottom))
如果您尝试裁剪较大的小图片,这将会中断,但我会假设您不会尝试(或者您可以捕捉到这种情况并且不会裁剪图像)。< / p>
答案 1 :(得分:6)
所提出的解决方案的一个潜在问题是在期望大小和旧大小之间存在奇怪差异的情况。你不能在每一边都有一个半像素。人们必须选择一面来增加一个像素。
如果水平方向存在奇怪的差异,则下面的代码会将额外的像素放在右边,如果垂直方向有奇数差异,则额外的像素会移到底部。
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
答案 2 :(得分:1)
我觉得最适合大多数应用程序的最简单解决方案仍然缺失。公认的答案存在像素不均匀的问题,尤其是对于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))
输出是在裁剪之前(代码中未显示):
之后:
图钉显示尺寸。
答案 3 :(得分:1)
我最初使用的是可接受的答案:
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
答案 4 :(得分:1)
可能我迟到了这个聚会,但至少我在这里 我想对图像进行中心裁剪,将9:16图像转换为16:9肖像至风景
这是我使用的算法:
代码:
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")
之前:
之后:
答案 5 :(得分:0)
作物中心及其周围:
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))