Home > Enterprise >  Problem with taking an array to a certain power
Problem with taking an array to a certain power

Time:04-06

So I'm trying to get a difference between certain row of a matrix and a pixel, and I'm getting an error.

Where colorPal is a 8x3 matrix:

colorPal = np.matrix('0., 0., 0.;'
                    '0., 0., 1.;'
                    '0., 1., 0.;'
                    '0., 1., 1.;'
                    '1., 0., 0.;'
                    '1., 0., 1.;'
                    '1., 1., 0.;'
                    '1., 1., 1.;')

, and I'm trying to subtract three values from RGB channels from certain row of that matrix:

colorPal[0] - pix

where pix is:

    a certain pixel with 3 channels (RGB) from image, 
and I'm accesing it by specifying row and column of that image (img):
    
So, pix = img[i,j]

For first row of colorPal and that certain pixel values are:

colorPal[0] = [[0. 0. 0.]]
pix = [0.81 0.81 0.81]

And after that operation above (colorPal[0] - pix) I'm getting a result:

[[-0.81 -0.81 -0.81]]

So it's getting subtracted. Now I want to take that whole row to second power ((colorPal[0] - pix)**2). But numpy throws this:

raise LinAlgError('Last 2 dimensions of the array must be square')                                                                                   
numpy.linalg.LinAlgError: Last 2 dimensions of the array must be square

How can I raise this whole row to the second power? What's wrong in this code?

CodePudding user response:

The problem is that you define it as a 2D matrix and the slice you're taking from it with colorPal[0] will still be a 2D matrix (even though 1 of the dimension now has size 1).

If you try to multiply that 2D matrix with itself, it requires the last two dimension to have the same size, which they don't, 1 != 3.

You could do this:

import numpy as np


colorPal = np.matrix('0., 0., 0.;'
                     '0., 0., 1.;'
                     '0., 1., 0.;'
                     '0., 1., 1.;'
                     '1., 0., 0.;'
                     '1., 0., 1.;'
                     '1., 1., 0.;'
                     '1., 1., 1.')

pix = np.array([0.81, 0.81, 0.81])

print((np.asarray(colorPal[0]).squeeze() - pix) ** 2)

This takes the slice and turns it into an array, with the same size and dimensions, and then squeezes it to turn it into a 1D array, which can be multiplied with itself as required.

Result:

[0.6561 0.6561 0.6561]

Or you can avoid the complexity, by turning all of colorPal into an array first, so you don't have to perform the transformation on every color:

import numpy as np


colorPal = np.matrix('0., 0., 0.;'
                     '0., 0., 1.;'
                     '0., 1., 0.;'
                     '0., 1., 1.;'
                     '1., 0., 0.;'
                     '1., 0., 1.;'
                     '1., 1., 0.;'
                     '1., 1., 1.')

pix = np.array([0.81, 0.81, 0.81])
colorPal = np.asarray(colorPal)

print((colorPal[0] - pix) ** 2)

Same result.

From your comment to this answer, it appears you want to actually modify or replace colorPal with the operation applied to each colour. Once you turn your matrix into an array, that's easy:

import numpy as np


colorPal = np.matrix('0., 0., 0.;'
                     '0., 0., 1.;'
                     '0., 1., 0.;'
                     '0., 1., 1.;'
                     '1., 0., 0.;'
                     '1., 0., 1.;'
                     '1., 1., 0.;'
                     '1., 1., 1.')

pix = np.array([0.81, 0.81, 0.81])
result = (np.asarray(colorPal) - pix) ** 2

print(result)

Result:

[[0.6561 0.6561 0.6561]
 [0.6561 0.6561 0.0361]
 [0.6561 0.0361 0.6561]
 [0.6561 0.0361 0.0361]
 [0.0361 0.6561 0.6561]
 [0.0361 0.6561 0.0361]
 [0.0361 0.0361 0.6561]
 [0.0361 0.0361 0.0361]]

Or you could do it all in-place after the type conversion:

colorPal = np.asarray(colorPal)
colorPal -= pix
colorPal *= colorPal
  • Related