问题
I have the following:
import numpy as np
XYZ_to_sRGB_mat_D50 = np.asarray([
[3.1338561, -1.6168667, -0.4906146],
[-0.9787684, 1.9161415, 0.0334540],
[0.0719453, -0.2289914, 1.4052427],
])
XYZ_1 = np.asarray([0.25, 0.4, 0.1])
XYZ_2 = np.random.rand(100,100,3)
np.matmul(XYZ_to_sRGB_mat_D50, XYZ_1) # valid operation
np.matmul(XYZ_to_sRGB_mat_D50, XYZ_2) # makes no sense mathematically
How do I perform the same operation on XYZ_2 that I would on XYZ_2? Do I somehow reshape the array first?
回答1:
It seems you are trying to sum-reduce
the last axis of XYZ_to_sRGB_mat_D50
(axis=1)
with the last one of XYZ_2
(axis=2)
. So, you can use np.tensordot like so -
np.tensordot(XYZ_2, XYZ_to_sRGB_mat_D50, axes=((2),(1)))
Related post to understand tensordot.
For completeness, we can surely use np.matmul
too after swappping last two axes of XYZ_2
, like so -
np.matmul(XYZ_to_sRGB_mat_D50, XYZ_2.swapaxes(1,2)).swapaxes(1,2)
This won't be as efficient as tensordot
one.
Runtime test -
In [158]: XYZ_to_sRGB_mat_D50 = np.asarray([
...: [3.1338561, -1.6168667, -0.4906146],
...: [-0.9787684, 1.9161415, 0.0334540],
...: [0.0719453, -0.2289914, 1.4052427],
...: ])
...:
...: XYZ_1 = np.asarray([0.25, 0.4, 0.1])
...: XYZ_2 = np.random.rand(100,100,3)
# @Julien's soln
In [159]: %timeit XYZ_2.dot(XYZ_to_sRGB_mat_D50.T)
1000 loops, best of 3: 450 µs per loop
In [160]: %timeit np.tensordot(XYZ_2, XYZ_to_sRGB_mat_D50, axes=((2),(1)))
10000 loops, best of 3: 73.1 µs per loop
Generally speaking, when it comes to sum-reductions
on tensors, tensordot
is much more efficient. Since, the axis of sum-reduction
is just one, we can make the tensor a 2D
array by reshaping, use np.dot
, get the result and reshape back to 3D
.
回答2:
You probably simply want this:
XYZ_2.dot(XYZ_to_sRGB_mat_D50.T)
np.matmul(XYZ_to_sRGB_mat_D50, XYZ_1)
is equivalent to XYZ_1.dot(XYZ_to_sRGB_mat_D50.T)
, you can then simply broadcast the operation to a 100 x 100 x 3 matrix.
来源:https://stackoverflow.com/questions/47646789/numpy-matrix-multiple-3x3-and-100x100x3-arrays