如何使用numpy沿轴制造Hadamard产品?

时间:2018-12-23 23:52:07

标签: python arrays numpy numpy-broadcasting numpy-ufunc

我正在尝试使用2-D阵列制作3-D的Hadamard产品。 2-D数组具有3-D数组的前两个轴的形状,因此应沿着2轴(因此是第3轴)移动以进行乘法运算,这意味着:将Hadamard乘积设为切片0,然后设为切片1,等等(参见图片,示意图)。

原始3D数组是opencv图像,因此形状为f。 (1080, 1920, 3)。二维数组是该图像的一个切片,因此其形状为(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]

但是,我不想在代码中进行两次此计算。

我尝试过:

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

尽管这在使用二维和一维数组时有效

>>> 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)

但是我想这是行不通的,因为它是为一维函数设计的...

Desired array multiplication

2 个答案:

答案 0 :(得分:1)

看看broadcasting的工作方式。本质上,您可以附加一个轴以执行按元素进行的操作,例如,可以这样做

class MyQsciScintilla : public QsciScintilla
{
    Q_OBJECT
public:
    explicit MyQsciScintilla(QWidget *parent = nullptr);
    void contextMenuEvent(QContextMenuEvent *event);
    //....
};

void MyQsciScintilla::contextMenuEvent(QContextMenuEvent *event)
{
    QMenu *menu = createStandardContextMenu();

    menu->addAction(tr("My Menu Item"));
    //...
    menu->exec(event->globalPos());
    delete menu;
}

答案 1 :(得分:0)

您可以使用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))))