Hal T - 6 months ago 49

Python Question

I know that in numpy you can't simply do conditionals on arrays as it doesn't know how to treat them and that this error is a result of that, however in my case my code is a lot simpler. I have:

`# H and _H are 3x3 arrays with hand-assigned values`

# uv1 is 3x57600 array of coordinates, hand assigned in a loop

HH = np.dot(_H,np.linalg.inv(H))

new_uv = np.dot(HH,uv1)

du = uv1[0,:] * new_uv[2,:]

u = new_uv[0,:] - du

u_greater_5 = u > 5

And the last line gives me the "ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()" error. u is of shape (57600,) and I can open up the interactive prompt and the following works fine:

`>>> a = np.array([1,2,3,4,5])`

>>> a > 3

array([False, False, False, True, True], dtype=bool)

But the code in the previous block doesn't. I've also tried

`np.greater(u,5)`

u[u>5] = 1

But they give the same error as well. Any ideas?

Also, I don't know if this is related, but bizarrely, trying to access u[0] gives me a 3-vector of the same 3 values (the first value in u) whereas it should be a scalar? Considering its shape is (57600,) ?

Edit: the traceback, as per request:

`Traceback (most recent call last):`

File "ros2vid.py", line 333, in <module>

process_frames(bag)

File "ros2vid.py", line 239, in process_frames

u_greater_5 = u > 5

ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()

Here's how I generate uv1:

`# frame is an image loaded from a ros bag`

uv1 = []

im_r = frame.shape[0]

im_c = frame.shape[1]

for i in range(1, im_r):

for j in range(im_c):

uv1.append([j, i, 1])

uv1 = np.transpose(np.array(uv1))

and the values of H and _H are just numbers I hard code in by hand. Something like:

`h11 = u0 * cosphi`

h12 = -alph_u

h13 = alph_u + u0 * (-cosphi + cz * sinphi)

h21 = -alph_u * sinphi + v0 * cosphi

h22 = 0

h23 = alph_v * (sinphi + cz * cosphi) + v0 * (-cosphi + cz * sinphi)

h31 = cosphi

h32 = 0

h33 = -cosphi + cz * sinphi

H = np.array([[h11, h12, h13], [h21, h22, h23], [h31, h32, h33]])

All the values up there like u0, cosphi, cz, etc. are simply scalars. I've individually checked them, and _H is assigned similarly as well. I've checked the shapes of H and _H and verified them to be 3x3.

Weirdly, I just tried u == 5 and that doesn't give me an error, u > 5 does.

Answer

I suspect that `u`

is a one-dimensional array of *objects*, and the objects are themselves one-dimensional numpy arrays with length 3. I can reproduce the behavior you report as follows. First, create a one-dimensional array of objects (length 3), and fill it with numpy arrays:

```
In [26]: u = np.empty(3, dtype=object)
In [27]: u[:] = [np.array([1, 2, 3]), np.array([4, 5, 6]), np.array([7, 8, 9])]
```

Check the type and attributes of `u`

. First, it is a numpy array with shape (3,).

```
In [28]: type(u)
Out[28]: numpy.ndarray
In [29]: u.shape
Out[29]: (3,)
```

The first element of `u`

is an array with length 3:

```
In [30]: u[0]
Out[30]: array([1, 2, 3])
```

The `dtype`

of `u`

is `dtype('O')`

, which is numpy's representation for the `object`

data type. (If you *print* `u.dtype`

, it will show `object`

.)

```
In [31]: u.dtype
Out[31]: dtype('O')
```

Now try `u > 5`

:

```
In [32]: u > 5
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-32-7f680a2a9455> in <module>()
----> 1 u > 5
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
```

`u == 5`

doesn't generate an error, but it does generate a warning, and returns the *scalar* False:

```
In [33]: u == 5
/Users/warren/miniconda3/bin/ipython:1: DeprecationWarning: elementwise == comparison failed; this will raise an error in the future.
#!/bin/bash /Users/warren/miniconda3/bin/python.app
Out[33]: False
```

To figure out why `u`

is an object array, you can work backwards, checking the `.shape`

and `.dtype`

attributes of the variables that you use to create `u`

.