Home > Net >  Python - How to convert for loop to numpy array
Python - How to convert for loop to numpy array

Time:10-01

I have been trying for a few days now to change this into a numpy array. This is being used to make a transparent image and putting it on the current frame.

Here is the code as a for loop:

    alpha_frame = frame[:,:,3] / 255.0
    alpha_foreground = foreground[:,:,3] / 255.0

    for color in range(0, 3):
            frame[:,:,color] = alpha_foreground * foreground[:,:,color]   \
                alpha_frame * frame[:,:,color] * (1 - alpha_foreground)

Here is what I've tried so far:

    alpha_frame = frame[:,:,3] / 255.0
    alpha_foreground = foreground[:,:,3] / 255.0

    color = np.arange(0,3)
    frame[:,:,color] = alpha_foreground * foreground[:,:,color]   \
    alpha_frame * frame[:,:,color] * (1 - alpha_foreground)
    return frame

Here is the error:

frame = alpha_foreground * foreground   \ 
ValueError: operands could not be broadcast together with shapes (480,640) (480,640,4)

CodePudding user response:

what's wrong with

frame = alpha_foreground * foreground   
      alpha_frame * frame * (1 - alpha_foreground)

?

CodePudding user response:

So first, if what you are looking for is a performance gain, instead of

alpha_frame = frame[:,:,3] / 255.0
alpha_foreground = foreground[:,:,3] / 255.0

for color in range(0, 3):
        frame[:,:,color] = alpha_foreground * foreground[:,:,color]   \
            alpha_frame * frame[:,:,color] * (1 - alpha_foreground)

I would recommend

alpha_foreground = foreground[:,:,3] / 255.0
alpha_frame = (1 - alpha_foreground) * (frame[:,:,3] / 255.0)


for color in range(0, 3):
        frame[:,:,color] = alpha_foreground * foreground[:,:,color]   \
            alpha_frame * frame[:,:,color]

Which saves a element-wise multiplication in the loop. And then, if you want to avoid the loop, it'd try:

alpha_foreground = np.zeros((4, foreground.shape[0], foreground.shape[1]))
alpha_foreground[:, :, :] = foreground[:,:,3] / 255.0
alpha_foreground = alpha_foreground.transpose((1, 2, 0))

alpha_frame = np.zeros((4, frame.shape[0], frame.shape[1]))
alpha_frame[:, :, :] = frame[:,:,3] / 255.0
alpha_frame = alpha_frame.transpose((1, 2, 0)) * (1 - alpha_foreground)

frame = alpha_foreground * foreground   alpha_frame * frame

The numpy broadcasting rules makes it so that if you want to broadcast a 2D array in a 3D array, the dimensions that should match are the last two.

This is correct: n*m broadcasted to k*n*m

This is not: n*m broadcasted to n*m*k

Thus, the fastest solution for broadcasting n*m to n*m*k is to create a k*n*m empty array, broadcast the n*m array and transpose the dimensions.

Careful, a simple .transpose() will turn k*n*m into m*n*k, which isn't what we want, so we have to pass a transposition to .transpose()

  • Related