Python 高效对中和叠加numpy阵列

Python 高效对中和叠加numpy阵列,python,arrays,numpy,Python,Arrays,Numpy,我有两个三维uint8numpy数组表示的RGBA图像数据。我想将其中一个(image)放在另一个(canvas)的中间。图像的宽度和高度通常会小于画布的相应尺寸,但它们可能会更大——在这种情况下,将使用图像的中心部分,并且会完全模糊画布。在所有情况下,输出都是画布的大小和形状 我可以做到这一点而不会出错,但我很惊讶代码最终是多么的不符合逻辑: h, w = canvas.shape[ :2 ] # canvas.shape is [ h, w, 4 ] because it is an

我有两个三维
uint8
numpy数组表示的RGBA图像数据。我想将其中一个(
image
)放在另一个(
canvas
)的中间。
图像
的宽度和高度通常会小于
画布
的相应尺寸,但它们可能会更大——在这种情况下,将使用
图像
的中心部分,并且会完全模糊
画布
。在所有情况下,输出都是
画布的大小和形状

我可以做到这一点而不会出错,但我很惊讶代码最终是多么的不符合逻辑:

h, w = canvas.shape[ :2 ]    # canvas.shape is [ h, w, 4 ] because it is an RGBA image
ih, iw = image.shape[ :2 ]   # image.shape is [ ih, iw, 4 ] because it is an RGBA image
xoffset = ( w - iw ) / 2.0
yoffset = ( h - ih ) / 2.0
xoffset = [ int( math.ceil( xoffset ) ), int( math.floor( xoffset ) ) ] # how much free space left and right
yoffset = [ int( math.ceil( yoffset ) ), int( math.floor( yoffset ) ) ] # how much free space top and bottom
if xoffset[ 0 ] < 0:
    image = image[ :, -xoffset[ 0 ]:, : ]
    iw += xoffset[ 0 ]
    xoffset[ 0 ] = 0
if xoffset[ 1 ] < 0:
    image = image[ :, :xoffset[ 1 ],  : ]
    iw += xoffset[ 1 ]
    xoffset[ 1 ] = 0
if yoffset[ 0 ] < 0:
    image = image[ -yoffset[ 0 ]:, :, : ]
    ih += yoffset[ 0 ]
    yoffset[ 0 ] = 0
if yoffset[ 1 ] < 0:
    image = image[ :yoffset[ 1 ],  :, : ]
    ih += yoffset[ 1 ]
    yoffset[ 1 ] = 0
canvas[ yoffset[ 0 ]:yoffset[ 0 ] + ih, xoffset[ 0 ]:xoffset[ 0 ] + iw, : ] = image
h,w=canvas.shape[:2]#canvas.shape是[h,w,4],因为它是RGBA图像
ih,iw=image.shape[:2]#image.shape是[ih,iw,4],因为它是RGBA图像
xoffset=(w-iw)/2.0
yoffset=(h-ih)/2.0
xoffset=[int(math.ceil(xoffset)),int(math.floor(xoffset))]#左右有多少可用空间
yoffset=[int(math.ceil(yoffset)),int(math.floor(yoffset))]#顶部和底部有多少可用空间
如果xoffset[0]<0:
image=image[:,-xoffset[0]:,:]
iw+=xoffset[0]
xoffset[0]=0
如果xoffset[1]<0:
image=image[:,:xoffset[1],:]
iw+=xoffset[1]
xoffset[1]=0
如果yoffset[0]<0:
image=image[-yoffset[0]:,:,:,:]
ih+=yoffset[0]
yoffset[0]=0
如果yoffset[1]<0:
image=image[:yoffset[1],:,:]
ih+=yoffset[1]
yoffset[1]=0
画布[yoffset[0]:yoffset[0]+ih,xoffset[0]:xoffset[0]+iw,:]=image

您能找到一种更优雅/可读/可维护的方法来做到这一点吗?一定有比我更好的解决办法。如果我知道
numpy
包含一些我还没猜到名字的功能,但它们可以在一行中完成…

我想你可以通过认识到每个维度的逻辑都是相同的来简化这一点,因此,您可以编写一个函数来处理每个维度并输出适当的数组切片。然后在两个维度上调用该函数,并将切片应用于数组。例如:

import numpy as np

def get_slices_1D(canvas_size, image_size):
    buffer = abs(canvas_size - image_size) // 2
    if canvas_size > image_size:
        return slice(buffer, buffer + image_size), slice(None)
    else:
        return slice(None), slice(buffer, buffer + canvas_size)

def get_slices_ND(canvas_shape, image_shape):
    pairs = zip(canvas_shape, image_shape)
    return zip(*(get_slices_1D(*pair) for pair in pairs))
现在让我们测试一下:

image = np.ones((3, 7, 4))
canvas = np.zeros((5, 5, 4))

ind_can, ind_im = get_slices_ND(canvas.shape, image.shape)
canvas[ind_can] = image[ind_im]

canvas[:, :, 0]
# array([[ 0.,  0.,  0.,  0.,  0.],
#        [ 1.,  1.,  1.,  1.,  1.],
#        [ 1.,  1.,  1.,  1.,  1.],
#        [ 1.,  1.,  1.,  1.,  1.],
#        [ 0.,  0.,  0.,  0.,  0.]])

作为奖励,这种方法可以推广到任意维数的数组

这当然更整洁。我缺少的关键洞见是,非常相似的计算切片可以用于分配的两侧。如果有一个原生的
numpy
one行程序,我仍然不会感到惊讶。