簡體   English   中英

測試 numpy 數組是否是 numpy 數組列表的成員,並將其從列表中刪除

[英]Test if a numpy array is a member of a list of numpy arrays, and remove it from the list

在測試 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)

我得到:

ValueError:包含多個元素的數組的真值不明確。 使用 a.any() 或 a.all()

然而,答案很明確: c正是CNTS[1] ,所以c in CNTS應該返回 True!

如何正確測試 numpy 數組是否是 numpy 數組列表的成員?

刪除時會發生同樣的問題:

CNTS.remove(c)

ValueError:包含多個元素的數組的真值不明確。 使用 a.any() 或 a.all()

應用程序:測試opencv輪廓(numpy 數組)是否是輪廓列表的成員,例如參見Remove an opencv contour from a list of contours

您收到錯誤是因為in基本上對CNTS每個元素x調用bool(c == x) 這是引發錯誤的__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()

這同樣適用於刪除,因為它測試每個元素的相等性。

遏制

解決方案是使用np.array_equal或將all方法應用於每個比較:

any(np.array_equal(c, x) for x in CNTS)

或者

any((c == x).all() for x in CNTS)

移動

要執行刪除,您對元素的索引比它的存在更感興趣。 我能想到的最快方法是迭代索引,使用CNTS的元素作為比較鍵:

index = next((i for i, x in enumerate(CNTS) if (c == x).all()), -1)

這個選項可以很好地短路,並返回-1作為默認索引而不是引發StopIteration 如果您更喜歡錯誤,可以將參數-1刪除到next 如果您願意,可以將(c == x).all() np.array_equal(c, x) (c == x).all()替換為np.array_equal(c, x)

現在您可以像往常一樣刪除:

del CNTS[index]

此解決方案適用於這種情況:

def arrayisin(array, list_of_arrays):
    for a in list_of_arrays:
        if np.array_equal(array, a):
            return True
    return False

此函數迭代數組列表並測試其他數組的相等性。 所以用法是:

>>> arrayisin(c, CNTS)
True

要從列表中刪除數組,您可以獲取數組的索引,然后使用list.pop 在函數get_index ,我們枚舉數組列表,這意味着我們壓縮列表的索引和列表的內容。 如果有匹配項,我們返回匹配項的索引。

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)

list.pop的文檔請參見python數據結構教程https://docs.python.org/3/tutorial/datastructures.html

使用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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM