我有两个数组A、B,它们的形状都是(42、28、4),其中:
42 : y_dim
28 : x_dim
4 : RGBA
## I'm on MacBook Air M1 2020 16Gb btw
我想通过一个类似的过程将它们结合在一起:
def add(A, B):
X = A.shape[1]
Y = A.shape[0]
alpha = A[..., 3] / 255
B[..., :3] = blend(B[..., :3], A[..., :3], alpha.reshape(Y, X, 1))
return B
def blend(c1, c2, alpha):
return np.asarray((c1 + np.multiply(c2, alpha))/(np.ones(alpha.shape) + alpha), dtype='uint8')
但目前这个速度有点太慢了(大约20毫秒,250幅图像叠加在一个基本数组[1]上),如果你有任何方法来改善这一点(最好是支持8位阿尔法),我很乐意知道.
[1]:
start = time.time()
for obj in l: # len(l) == 250
_slice = np.index_exp[obj.y * 42:(obj.y+1) * 42, obj.x * 28 : (obj.x+1) * 28, :]
self.pixels[_slice] = add(obj.array, self.pixels[_slice])
stop = time.time()
>>> stop - start # ~20ms
我试过以下方法:
# cv2.addWeighted() in add()
## doesn't work because it has one alpha for the whole image,
## but I want to have indiviual alpha control for each pixel
B = cv.addWeighted(A, 0.5, B, 0.5, 0)
# np.vectorize blend() and use in add()
## way too slow because as the docs mention it's basically just a for-loop
B[..., :3] = np.vectorize(blend)(A[..., :3], B[..., :3], A[..., 3] / 255)
# changed blend() to the following
def blend(a, b, alpha):
if alpha == 0:
return b
elif alpha == 1:
return a
return (b + a * alpha) / (1 + alpha)
# moved the blend()-stuff to add()
## doesn't combine properly; too dark with alpha
np.multiply(A, alpha.reshape(Y, X, 1)) + np.multiply(B, 1 - alpha.reshape(Y, X, 1))
我也试过一些比特的东西,但我的猴脑不能正确理解它.我使用的是M1 Mac,所以如果你有任何metalcompute和Python的经验,请包括任何关于这方面的 idea !
任何输入是欢迎的,提前感谢!
Answer:克里斯托夫·拉克维茨发布了一个非常详细和 struct 良好的答案,所以如果你对类似的事情感兴趣,请查看下面接受的推荐.
为了补充这一点,我在我的M1计算机上运行Christoph的代码来显示结果.
2500 calls (numpy) = 0.0807
2500 calls (other) = 0.0833
2500 calls (Christoph´s) = 0.0037