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行程序,我仍然不会感到惊讶。