2

Firstly, sorry if this is in fact a duplicate - I have spent the last three hours attempting to solve this problem and haven't been able to find any solution.

Problem

I am using lists to represent coordinates as [x, y]. I want to find out if a list of coordinates does not contain a specified coordinate. For example, if I have the list of coordinates [[3.3, 4.4], [5.5, 6.6]] and the coordinate [1.1, 2.2], I want a return of True, because the coordinate is not in the list of coordinates.

It may be worth noting that the list of coordinates is generated using the OpenCV functions cv2.findContours(), cv2.minAreaRect() and finally cv2.boxPoints() which results in a list of lists. These coordinates are stored in a dict and accessed from there; calling a print() of the coordinates gives me the coordinates in the format [array([3.3, 4.4], dtype=float32), array([5.5, 6.6], dtype=float32)] as opposed to the format [[3.3, 4.4], [5.5, 6.6]] which is given when I print() the coordinates straight after finding them with cv2.boxPoints().

What I have tried

I have tried to use the answer to this question but I get the error ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all().

The code for that attempt looks like this:

for coordinate in box:
    if coordinate not in specialCoordinates:
        # operations go here

I then attempted to use the answer to this question about a.all() but I get the same error.

The code for that attempt looks like this:

for coordinate in box:
    if not all(coordinate == special for special in specialCoordinates):
        # operations go here

I also tried this:

for coordinate in box:
    if all(coordinate != special for special in specialCoordinates):
        # operations go here

Additional information

The format mentioned above if coordinate not in specialCoordinates works when I try the following in the Python 2.7 interpreter:

Python 2.7.15 (v2.7.15:ca079a3ea3, Apr 30 2018, 16:30:26) [MSC v.1500 64 bit (AMD64)] on win32

Type "help", "copyright", "credits" or "license" for more information.

>>> a = [[3.3, 4.4], [5.5, 6.6]]

>>> b = [1.1, 2.2]

>>> b not in a

True

eyllanesc
  • 235,170
  • 19
  • 170
  • 241
NJRBailey
  • 69
  • 2
  • 4
  • Welcome to StackOverflow. Please read and follow the posting guidelines in the help documentation, as suggested when you created this account. [Minimal, complete, verifiable example](http://stackoverflow.com/help/mcve) applies here. We cannot effectively help you until you post your MCVE code and accurately describe the problem. We should be able to paste your posted code into a text file and reproduce the problem you described. – Prune Oct 31 '18 at 17:46
  • You're close, but we need you to shorten this to a representative example, rather than a screenful of the history. `OpenCV` isn't an issue, but `numpy` is. Give a simple example with constants for your in-program structures, and *then* the `for coordinate in box` loop(s) you want us to fix. – Prune Oct 31 '18 at 17:48
  • If you have a list of arrays you can convert that to a list of lists with `map(list, specialCoordinates)` – CJR Oct 31 '18 at 17:49
  • You saying that python 2.7 works, so what's not working? – Rocky Li Oct 31 '18 at 17:56

2 Answers2

0

The main problem here is that the numpy array elements in the list have precision associated with them for example: a = [np.array([3.3, 4.4], dtype='float32'), np.array([5.5, 6.6], dtype='float32')] Which is equivalent to: [array([ 3.29999995, 4.4000001 ], dtype=float32), array([ 5.5 , 6.5999999], dtype=float32)]

Hence, if you look for [3.3, 4.4] in a, it won't be there so you might want to play around with the precision or do a bit of casting.

Konstantin Grigorov
  • 1,356
  • 12
  • 20
  • That is not the main problem. The main problem is that if you do something like `if (np.random.randint(5,size=5) == 0)`, you will get `ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()`. Because it's an array of booleans and what's the ground truth on that? – CJR Oct 31 '18 at 18:04
0
import numpy as np
#a = [array([3.3, 4.4]), array([5.5, 6.6])]
a = np.array([i.tolist() for i in a])

def if_not_in_a(A, B):
    for i in A:
        if np.linalg.norm(i - B) == 0: 
        #you can use tolerance like < 1e-2 to avoid floating point complicacy
            return False
    return True

print(if_not_in_a(a, np.array([1.1, 2.2])))
#prints True

print(if_not_in_a(a, np.array([3.3, 4.4])))
#prints False
Osman Mamun
  • 2,864
  • 1
  • 16
  • 22