Итак, я пытаюсь получить разницу между определенной строкой матрицы и пикселем, и я получаю сообщение об ошибке.
Где colorPal — матрица 8x3:
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.;')
, и я пытаюсь вычесть три значения из каналов RGB из определенной строки этой матрицы:
colorPal[0] - pix
где пикс:
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]
Для первой строки colorPal и определенных значений пикселей:
colorPal[0] = [[0. 0. 0.]]
pix = [0.81 0.81 0.81]
И после этой операции выше (colorPal[0] - pix
) я получаю результат:
[[-0.81 -0.81 -0.81]]
Так что это вычитается. Теперь я хочу возвести весь этот ряд во вторую степень ((colorPal[0] - pix)**2
). Но numpy выдает это:
raise LinAlgError('Last 2 dimensions of the array must be square')
numpy.linalg.LinAlgError: Last 2 dimensions of the array must be square
Как мне возвести весь этот ряд во вторую степень? Что не так в этом коде?
Странный. У меня python 3.10.4, а numpy 1.21.5.
Проблема в том, что вы определяете его как 2D-матрицу, и срез, который вы берете из него с помощью colorPal[0]
, по-прежнему будет 2D-матрицей (даже несмотря на то, что 1 измерение теперь имеет размер 1
).
Если вы попытаетесь умножить эту 2D-матрицу на себя, потребуется, чтобы последние два измерения имели одинаковый размер, а они не имеют, 1 != 3.
Вы можете сделать это:
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)
Это берет срез и превращает его в массив с тем же размером и измерениями, а затем сжимает его, чтобы превратить его в одномерный массив, который можно умножать сам на себя по мере необходимости.
Результат:
[0.6561 0.6561 0.6561]
Или вы можете избежать сложности, сначала превратив все colorPal
в массив, поэтому вам не нужно выполнять преобразование для каждого цвета:
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)
Тот же результат.
Из вашего комментария к этому ответу видно, что вы действительно хотите изменить или заменить colorPal
операцией, применяемой к каждому цвету. Как только вы превратите свою матрицу в массив, это легко:
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)
Результат:
[[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]]
Или вы можете сделать все это на месте после преобразования типа:
colorPal = np.asarray(colorPal)
colorPal -= pix
colorPal *= colorPal
Я вижу, я вижу. Но как именно это работает? Если я распечатаю colorPal после и до преобразования, внутренности выглядят одинаково. Это просто изменение типа объекта?
colorPal
выглядит одинаково, потому что код не изменяет его (или только меняет тип) — я только показывал, почему вы получаете ошибку, которую вы получали, и как ее обойти. Если вы хотите обновить сам colorPal
или сохранить результат вычисления где-то еще, см. мое обновление к ответу.
Проблема в том, что вы используете np.matrix
. Вместо этого вы должны использовать np.array
.
*
-оператор (**
-оператор)...
np.matrix
это матрица-умножение (и возведение в степень).np.array
это умножение поэлементно (и возведение в степень).Проблема ничего связана с фрагментами из np.matrix
, поддерживающими количество измерений.
Если вы хотите продолжать использовать np.matrix
, вам понадобятся np.asarray()
или np.array()
для преобразования матриц в массивы. Затем вы можете наслаждаться поэлементными операциями.
Обратите внимание, что существует @
-оператор, и он определен как умножение матриц (для объектов np.array). A @ B
эквивалентно np.matmul(A, B)
. Также существует np.dot
. Поведение этих функций чувствительно к формам входных данных.
Какую версию numpy и Python вы используете? Ваш исходный фрагмент кода не будет работать на Python 3.10 и numpy 1.22.0. (финал
;
оскорбляет)