我正在尝试编写一些代码来编写单float
个值,因此使用1D(最终是2D)numpy.arrays
作为输入可以正常工作。
向下缩小到一个最小的例子,该函数看起来像这样(没有这个例子没有做任何有用的事情,但是如果删除了do_math
和do_some_more_math
,它将产生完全描述的行为):< / p>
def do_complicated_math(r, g, b):
rgb = numpy.array([r, g, b])
# Math! No change in array shape. To run example just comment out.
rgb = do_math(rgb)
m_2 = numpy.array([[rgb[0], 0, 0], [0, rgb[1], 0], [0, 0, rgb[2]]])
# Get additional matrices needed for transformation.
# These are actually predefined 3x3 float arrays
m_1 = numpy.ones((3, 3))
m_3 = numpy.ones((3, 3))
# Transform the rgb array
rgb_transformed = m_1.dot(m_2).dot(m_3).dot(rgb)
# More math! No change in array shape. To run example just comment out.
rgb_transformed = do_some_more_math(rgb_transformed)
# Almost done just one more thing...
return numpy.arctan2(rgb_transformed, rgb_transformed)
# Works fine
do_complicated_math(1, 1, 1)
# Fails
x = numpy.ones(6)
do_complicated_math(x, x, x)
此功能可以正常工作,因为r
,g
和b
是个别数字,但是,如果它们是numpy.array
(例如,按顺序)要一次转换多个rgb值,numpy.arctan2
会引发以下异常:
Traceback (most recent call last):
(...) line 32, in do_complicated_math
numpy.arctan2(rgb_transformed, rgb_transformed)
AttributeError: 'numpy.ndarray' object has no attribute 'arctan2'
我没有找到任何明确的答案,告诉我这是什么。似乎工作正常的arctan2
与多维数组一起使用,如下所示:
numpy.arctan2(numpy.ones((3,4,5)), numpy.ones((3,4,5)))
所以我认为问题必须出在m_2
的创建方式,或m_1
,m_2
,m_3
和rgb
的乘法之间得到传播,但我似乎无法弄清楚它在哪里。
答案 0 :(得分:3)
问题是rgb_transformed
在将它传递给arctan2
时不再是标准的numpy数组,它已成为一个对象数组:
print rgb_transformed
"""[[array([ 9., 9., 9., 9., 9., 9.])
array([ 9., 9., 9., 9., 9., 9.])
array([ 9., 9., 9., 9., 9., 9.])
array([ 9., 9., 9., 9., 9., 9.])
array([ 9., 9., 9., 9., 9., 9.])
array([ 9., 9., 9., 9., 9., 9.])]
[array([ 9., 9., 9., 9., 9., 9.])
array([ 9., 9., 9., 9., 9., 9.])
array([ 9., 9., 9., 9., 9., 9.])
array([ 9., 9., 9., 9., 9., 9.])
array([ 9., 9., 9., 9., 9., 9.])
array([ 9., 9., 9., 9., 9., 9.])]
[array([ 9., 9., 9., 9., 9., 9.])
array([ 9., 9., 9., 9., 9., 9.])
array([ 9., 9., 9., 9., 9., 9.])
array([ 9., 9., 9., 9., 9., 9.])
array([ 9., 9., 9., 9., 9., 9.])
array([ 9., 9., 9., 9., 9., 9.])]]"""
print rgb_transformed.shape
#(3, 6)
print rgb_transformed.dtype
#object
所以这个问题比我想象的要简单:
这一行:
m_2 = numpy.array([[rgb[0], 0, 0], [0, rgb[1], 0], [0, 0, rgb[2]]])
print m_2
#array([[array([ 1., 1., 1., 1., 1., 1.]), 0, 0],
# [0, array([ 1., 1., 1., 1., 1., 1.]), 0],
# [0, 0, array([ 1., 1., 1., 1., 1., 1.])]], dtype=object)
这里创建了对象数组,并通过代码的其余部分进行传播。
修改强>
要解决此问题,您可能需要稍微不同地广播您的阵列。基本上更改外部维度以反映不断变化的rgb
值。 免责声明:我没有很好的方法在您的问题的背景下验证结果,所以请小心对待输出。
import numpy as np
def do_complicated_math(r, g, b):
rgb = np.array([r, g, b])
# create a transposed version of the m_2 array
m_2 = np.zeros((r.size,3,3))
for ii,ar in enumerate(rgb):
m_2[:,ii][:,ii][:] = ar
m_1 = np.ones((3, 3))
m_3 = np.ones((3, 3))
rgb_transformed = m_1.dot(m_2).dot(m_3).dot(rgb)
print rgb_transformed
return np.arctan2(rgb_transformed, rgb_transformed)
x = np.ones(6)
do_complicated_math(x, x, x)
r = np.array([0.2,0.3,0.1])
g = np.array([1.0,1.0,0.2])
b = np.array([0.3,0.3,0.3])
do_complicated_math(r, g, b)
这仅适用于数组作为输入,但添加单个值的处理作为输入应该是微不足道的。