Как сделать продукт Адамара по оси с клочком?

Я пытаюсь сделать продукт Адамара 3-D с 2-D массивом. 2-D массив разделяет форму первых двух осей 3-D массива и должен быть перемещен вдоль 2-й оси (таким образом, 3-й) для умножения, что означает: сделать продукт Адамара с срезом 0, затем срезом 1, и т. д. (ср. изображение, схема).

Оригинальный трехмерный массив представляет собой opencv изображение, таким образом, имеет форму Fe (1080, 1920, 3), 2-D массив представляет собой один фрагмент этого изображения, поэтому имеет форму (1080, 1920)

Есть ли способ сделать это без циклов или указания каждого среза самостоятельно? Или петли способ пойти сюда?

Что работает это:

    img_new = np.zeros(shape=img.shape[:2])
    img_new[0] = (img[:, :, 1] * img[:, :, 0])[0]
    img_new[1] = (img[:, :, 2] * img[:, :, 0])[1]

Тем не менее, я бы предпочел не использовать этот расчет 2 раза в коде.

Я пытался:

    img_new = np.multiply(img_cvt[:, :, 1:3], img[:, :, 0])

Хотя это работает при использовании 2-D и 1-D массива

>>> a = np.array(((1,2),(3,4)))
>>> b = np.array((5,8))
>>> np.multiply(a,b)
array([[ 5, 16],
       [15, 32]])

Это дает ошибку трансляции в 3-D/2-D случае:

ValueError: operands could not be broadcast together with shapes (1080,1920,2) (1080,1920)

То же относится и к np.apply_along_axis:

img_new = np.apply_along_axis(np.multiply, 2, img[:, :, 1:3], img[:, :, 0])

Что приводит к следующему:

ValueError: operands could not be broadcast together with shapes (2,) (1080,1920)

Но я думаю, что это не могло работать, потому что он предназначен для 1d функций...

1 ответ

Решение

Посмотрите, как работает вещание. По сути, вы можете добавить ось для выполнения поэлементных операций, например, это работает

import numpy as np

a = np.random.rand(10, 3)
b = np.random.rand(10, 3, 2)

c = b * a[..., np.newaxis] # make a shape 10 x 3 x 1

Вы можете использовать np.expand_dims() функция для этого.

Создайте кортеж с недостающими размерами, используя np.arange(), а затем просто добавьте их. (Я предполагаю, что вы хотите добавить в конце - вы всегда можете использовать транспонирование для этого):

c = np.array([
        [[1, 2, 3, 4],[5, 6, 7, 8]],
        [[.1, .2, .3, .4], [.5, .6, .7, .8]]
    ])
d = np.array([.5, .6])

cdim = len(c.shape)
ddim = len(d.shape)
newdims = tuple(np.arange(start=ddim, stop=cdim))
dx = np.expand_dims(d, newdims)

c + dx
c * dx

Очевидно, вы можете сделать все это в одной строке - переменные приведены только для ясности:

def match_dim(b, A):
    "Adds dimensions of length 1 to b to make it dimension compliant with A and returns the expanded structure"
    return np.expand_dims(b, tuple(np.arange(start=len(b.shape), stop=len(A.shape))))
Другие вопросы по тегам