0
votes

What is the most pythonic way to multiply each row(axis=2) of a np array with a matrix. For example, I am working with images read as np array of shape (480, 512, 3), I want to multiply each img[i,j] with a 3x3 matrix. I don't want to use for loops for this. This is what I tried but it gives an error

A = np.array([
        [.412453, .35758, .180423],
        [.212671, .71516, .072169],
        [.019334, .119193, .950227]
    ])
lin_XYZ = lambda x: np.dot(A, x[::-1])
#lin_XYZ = np.vectorize(lin_XYZ)
tmp_img = lin_XYZ(tmp_img[:,:])

File ".\proj1a.py", line 24, in color2luv
tmp_img = lin_XYZ(tmp_img[:,:])
File ".\proj1a.py", line 22, in <lambda>
lin_XYZ = lambda x: np.dot(A, x)

ValueError: shapes (3,3) and (480,512,3) not aligned: 3 (dim 1) != 512 (dim 1)

1
By "row" do you actually mean axis=2 or axis=1? (since first axis, the column axis, would be axis=0?) - heltonbiker
Looks like what you want is simply x.dot(A) not A.dot(x). - Julien
You could reshape your matrix, say, from MxNx3, to Ox3, with O = M*N, then multiply it, then reshape it again. - heltonbiker
@AGNGazer, please reference : stackoverflow.com/help/be-nice - Stephen Rauch
@AGNGazer sorry I'll try to improve next time, but I am not trying to multiply (480,512) by 3x3, what I meant was each img[i,j] would give a row with 3 elements and then multiply it with the 3x3 matrix, I'll try to describe the problem better next time @heltonbiker I'll try that - pradystar

1 Answers

1
votes

So A is (3,3) and x is (480, 512, 3), and you what is a dot on the size 3 dimension. The key thing to remember with dot(A,B) is, last dim of A with 2nd to the last of B. (That's what the error is complaining about 3 (dim 1) != 512 (dim 1))

x.dot(A)
x.dot(A.T)

would meet that requirement.

A.dot(x.transpose(0,2,1))   #  (3,3) with (480,3,512) 

would also work, though the resulting array may need further transposing - assuming you want the 3 to be last.

You can also pair dimensions with einsum or tensordot:

np.einsum('ij,kli->klj', A, x)

x[::-1] flips x on its first dimenion, the 480 one. Shape remains the same. Did you want the transpose?