[英]Test if a numpy array is a member of a list of numpy arrays, and remove it from the list
When testing if a numpy array c
is member of a list of numpy arrays CNTS
:在测试 numpy 数组
c
是否是 numpy 数组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)
I get:我得到:
ValueError: The truth value of an array with more than one element is ambiguous.
ValueError:包含多个元素的数组的真值不明确。 Use a.any() or a.all()
使用 a.any() 或 a.all()
However, the answer is rather clear: c
is exactly CNTS[1]
, so c in CNTS
should return True!然而,答案很明确:
c
正是CNTS[1]
,所以c in CNTS
应该返回 True!
How to correctly test if a numpy array is member of a list of numpy arrays?如何正确测试 numpy 数组是否是 numpy 数组列表的成员?
The same problem happens when removing :删除时会发生同样的问题:
CNTS.remove(c)
ValueError: The truth value of an array with more than one element is ambiguous.
ValueError:包含多个元素的数组的真值不明确。 Use a.any() or a.all()
使用 a.any() 或 a.all()
Application: test if an opencv
contour (numpy array) is member of a list of contours, see for example Remove an opencv contour from a list of contours .应用程序:测试
opencv
轮廓(numpy 数组)是否是轮廓列表的成员,例如参见Remove an opencv contour from a list of contours 。
You are getting the error because in
essentially invokes bool(c == x)
on every element x
of CNTS
.您收到错误是因为
in
基本上对CNTS
每个元素x
调用bool(c == x)
。 It's the __bool__
conversion that is raising the error:这是引发错误的
__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()
The same applies for removal, since it tests for equality with each element.这同样适用于删除,因为它测试每个元素的相等性。
Containment遏制
The solution is to use np.array_equal
or apply the all
method to each comparison:解决方案是使用
np.array_equal
或将all
方法应用于每个比较:
any(np.array_equal(c, x) for x in CNTS)
OR或者
any((c == x).all() for x in CNTS)
Removal移动
To perform the removal, you are more interested in the index of the element than its existence.要执行删除,您对元素的索引比它的存在更感兴趣。 The fastest way I can think of is to iterate over the indices, using the elements of
CNTS
as comparison keys:我能想到的最快方法是迭代索引,使用
CNTS
的元素作为比较键:
index = next((i for i, x in enumerate(CNTS) if (c == x).all()), -1)
This option short circuits quite nicely, and returns -1
as the default index rather than raising a StopIteration
.这个选项可以很好地短路,并返回
-1
作为默认索引而不是引发StopIteration
。 You can remove the argument -1
to next
if you prefer the error.如果您更喜欢错误,可以将参数
-1
删除到next
。 If you prefer, you can replace (c == x).all()
with np.array_equal(c, x)
.如果您愿意,可以将
(c == x).all()
np.array_equal(c, x)
(c == x).all()
替换为np.array_equal(c, x)
。
Now you can remove as usual:现在您可以像往常一样删除:
del CNTS[index]
This solution could work for this case:此解决方案适用于这种情况:
def arrayisin(array, list_of_arrays):
for a in list_of_arrays:
if np.array_equal(array, a):
return True
return False
This function iterates over a list of arrays and tests the equality against some other array.此函数迭代数组列表并测试其他数组的相等性。 So the usage would be:
所以用法是:
>>> arrayisin(c, CNTS)
True
To remove the array from the list, you can get the index of the array and then use list.pop
.要从列表中删除数组,您可以获取数组的索引,然后使用
list.pop
。 In the function get_index
, we enumerate the list of arrays, meaning we zip the indices of the list and the contents of the list.在函数
get_index
,我们枚举数组列表,这意味着我们压缩列表的索引和列表的内容。 If there is a match, we return the index of the match.如果有匹配项,我们返回匹配项的索引。
def get_index(array, list_of_arrays):
for j, a in enumerate(list_of_arrays):
if np.array_equal(array, a):
return j
return None
idx = get_index(c, CNTS) # 1
CNTS.pop(idx)
Please see the python data structures tutorial for the documentation of list.pop
https://docs.python.org/3/tutorial/datastructures.html list.pop
的文档请参见python数据结构教程https://docs.python.org/3/tutorial/datastructures.html
Use del
to delete the index of the list you want to remove.使用
del
要删除的列表的索引。
del CNTS[int(np.where(list(np.array_equal(row, c) for row in CNTS))[0])]
CNTS
[array([[[ 78, 1202]],
[[ 63, 1202]],
[[ 63, 1187]],
[[ 78, 1187]]]), array([[[ 72, 742]],
[[ 58, 742]],
[[ 57, 741]],
[[ 57, 727]],
[[ 58, 726]],
[[ 72, 726]]]), array([[[ 66, 194]],
[[ 51, 194]],
[[ 51, 179]],
[[ 66, 179]]])]
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.