测试numpy数组是否为numpy数组列表的成员,并将其从列表中删除

Bas*_*asj 5 python arrays numpy list

在测试numpy数组是否为numpy数组c列表的成员时CNTS

import numpy as np

c = np.array([[[ 75, 763]],
              [[ 57, 763]],
              [[ 57, 749]],
              [[ 75, 749]]])

CNTS = [np.array([[[  78, 1202]],
                  [[  63, 1202]],
                  [[  63, 1187]],
                  [[  78, 1187]]]),
        np.array([[[ 75, 763]],
                  [[ 57, 763]],
                  [[ 57, 749]],
                  [[ 75, 749]]]),
        np.array([[[ 72, 742]],
                  [[ 58, 742]],
                  [[ 57, 741]],
                  [[ 57, 727]],
                  [[ 58, 726]],
                  [[ 72, 726]]]),
        np.array([[[ 66, 194]],
                  [[ 51, 194]],
                  [[ 51, 179]],
                  [[ 66, 179]]])]

print(c in CNTS)
Run Code Online (Sandbox Code Playgroud)

我得到:

ValueError:具有多个元素的数组的真值不明确。使用a.any()或a.all()

但是,答案很明确:cCNTS[1],因此c in CNTS应返回True!

如何正确测试numpy数组是否为numpy数组列表的成员?

删除时发生相同的问题:

CNTS.remove(c)
Run Code Online (Sandbox Code Playgroud)

ValueError:具有多个元素的数组的真值不明确。使用a.any()或a.all()

应用程序:测试opencv轮廓(numpy数组)是否为轮廓列表的成员,例如,参见从轮廓列表中删除opencv轮廓

Mad*_*ist 5

你所得到的错误,因为in本质上调用bool(c == x)每一个元素上xCNTS。这__bool__是引发错误的转换:

>>> c == CNTS[1]
array([[[ True,  True]],
       [[ True,  True]],
       [[ True,  True]],
       [[ True,  True]]])

>>> bool(_)
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
Run Code Online (Sandbox Code Playgroud)

这同样适用于删除,因为它测试每个元素的相等性。

遏制

解决方案是对每个比较使用np.array_equal或应用该all方法:

any(np.array_equal(c, x) for x in CNTS)
Run Code Online (Sandbox Code Playgroud)

或者

any((c == x).all() for x in CNTS)
Run Code Online (Sandbox Code Playgroud)

移动

要执行删除,您对元素的索引比它的存在更感兴趣。我能想到的最快方法是迭代索引,使用 的元素CNTS作为比较键:

index = next((i for i, x in enumerate(CNTS) if (c == x).all()), -1)
Run Code Online (Sandbox Code Playgroud)

这个选项可以很好地短路,并-1作为默认索引返回而不是提高StopIteration. 您可以删除的说法-1next,如果你喜欢的错误。如果您愿意,可以替换(c == x).all()np.array_equal(c, x).

现在您可以像往常一样删除:

del CNTS[index]
Run Code Online (Sandbox Code Playgroud)

  • @巴斯杰。更新以包括移除 (2认同)