0

I have an 640x480 RGB image with numpy shape (480, 640, 3) -- 3 for the R, G, B channels and I would like to at each pixel, transform the RGB value according to:

    # for each pixel
    for i in range(img.shape[0]):
        for j in range(img.shape[1]):
            # set the new RGB value at that pixel to
            # (new RGB vector) = (const matrix A) * (old RGB vector) + (const vector B)
            img[i,j,:] = np.reshape((np.matmul(A, np.expand_dims(img[i,j,:], axis = 1)) + B), (3,))

Where A is of shape (3,3) and B is of shape (3,1). How do I do this with numpy without writing a loop over the pixels?

wuxiekeji
  • 1,772
  • 2
  • 15
  • 22
  • Your code doesn't work. `numpy.matmul(A, data[i,j,:].T) + B` returns shape (3,3) while `img[i,j,:]` has shape (3,). You assign shape `(3,3)` to `(3,)`. – Andy L. Oct 04 '20 at 22:29
  • @wuxiekeji Seemed like a typo - B must be `1D` array? – Divakar Oct 04 '20 at 22:40
  • I edited it in a way that I think it works, but either way, the intention is to do (constant matrix A)*(rgb vector) + (constant vector B) at each rgb pixel. – wuxiekeji Oct 05 '20 at 01:29
  • @wuxiekeji Did the posted solution work for you? – Divakar Oct 06 '20 at 08:51

1 Answers1

0

One way would be with np.einsum -

img = np.einsum('ij,klj->kli',A,data) + B

Another with np.tensordot -

img = np.tensordot(data,A,axes=(-1,-1)) + B

Related - Understanding tensordot

I assumed B to be 1D array. If not so, use B.ravel() in place of B.

Divakar
  • 218,885
  • 19
  • 262
  • 358