让我说我有一个宽x和高y的numpy图像。 我必须将图像的中心部分裁剪为宽度cropx和height cropy。让我们假设cropx和cropy是正非零整数并且小于相应的图像大小。什么是对输出图像应用切片的最佳方法?
答案 0 :(得分:25)
这些方面的东西 -
def crop_center(img,cropx,cropy):
y,x = img.shape
startx = x//2-(cropx//2)
starty = y//2-(cropy//2)
return img[starty:starty+cropy,startx:startx+cropx]
示例运行 -
In [45]: img
Out[45]:
array([[88, 93, 42, 25, 36, 14, 59, 46, 77, 13, 52, 58],
[43, 47, 40, 48, 23, 74, 12, 33, 58, 93, 87, 87],
[54, 75, 79, 21, 15, 44, 51, 68, 28, 94, 78, 48],
[57, 46, 14, 98, 43, 76, 86, 56, 86, 88, 96, 49],
[52, 83, 13, 18, 40, 33, 11, 87, 38, 74, 23, 88],
[81, 28, 86, 89, 16, 28, 66, 67, 80, 23, 95, 98],
[46, 30, 18, 31, 73, 15, 90, 77, 71, 57, 61, 78],
[33, 58, 20, 11, 80, 25, 96, 80, 27, 40, 66, 92],
[13, 59, 77, 53, 91, 16, 47, 79, 33, 78, 25, 66],
[22, 80, 40, 24, 17, 85, 20, 70, 81, 68, 50, 80]])
In [46]: crop_center(img,4,6)
Out[46]:
array([[15, 44, 51, 68],
[43, 76, 86, 56],
[40, 33, 11, 87],
[16, 28, 66, 67],
[73, 15, 90, 77],
[80, 25, 96, 80]])
答案 1 :(得分:11)
基于@Divakar答案的更通用的解决方案:
def cropND(img, bounding):
start = tuple(map(lambda a, da: a//2-da//2, img.shape, bounding))
end = tuple(map(operator.add, start, bounding))
slices = tuple(map(slice, start, end))
return img[slices]
如果我们有一个数组a
>>> a = np.arange(100).reshape((10,10))
array([[ 0, 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, 26, 27, 28, 29],
[30, 31, 32, 33, 34, 35, 36, 37, 38, 39],
[40, 41, 42, 43, 44, 45, 46, 47, 48, 49],
[50, 51, 52, 53, 54, 55, 56, 57, 58, 59],
[60, 61, 62, 63, 64, 65, 66, 67, 68, 69],
[70, 71, 72, 73, 74, 75, 76, 77, 78, 79],
[80, 81, 82, 83, 84, 85, 86, 87, 88, 89],
[90, 91, 92, 93, 94, 95, 96, 97, 98, 99]])
我们可以用cropND(a, (5,5))
剪辑它,你会得到:
>>> cropND(a, (5,5))
array([[33, 34, 35, 36, 37],
[43, 44, 45, 46, 47],
[53, 54, 55, 56, 57],
[63, 64, 65, 66, 67],
[73, 74, 75, 76, 77]])
它不仅适用于2D图像,还适用于3D图像。
度过愉快的一天。
答案 2 :(得分:1)
谢谢,Divakar。
你的回答让我朝着正确的方向前进。我使用负片偏移来计算结果':
def cropimread(crop, xcrop, ycrop, fn):
"Function to crop center of an image file"
img_pre= msc.imread(fn)
if crop:
ysize, xsize, chan = img_pre.shape
xoff = (xsize - xcrop) // 2
yoff = (ysize - ycrop) // 2
img= img_pre[yoff:-yoff,xoff:-xoff]
else:
img= img_pre
return img
答案 3 :(得分:0)
@Divakar的答案的一个简单修改,保留了图像通道:
def crop_center(self, img, cropx, cropy):
_, y, x = img.shape
startx = x // 2 - (cropx // 2)
starty = y // 2 - (cropy // 2)
return img[:, starty:starty + cropy, startx:startx + cropx]
答案 4 :(得分:0)
@Divakar答案中的另一个简单修改,用于保留颜色通道:
def crop_center(img,cropx,cropy):
y,x,_ = img.shape
startx = x//2-(cropx//2)
starty = y//2-(cropy//2)
return img[starty:starty+cropy,startx:startx+cropx,:]