簡體   English   中英

numpy數組中帶有通配符的二維模式匹配

[英]Two Dimensional Pattern Matching with Wildcards in Numpy Arrays

首先,我知道這個這個以及這個關於二維模式匹配的文章,但是這些文章都不包含通配符匹配。 此外,我知道有幾篇論文,如這一個已經解決我所面臨的問題。 但是,我只是熟悉二維數組中的模式匹配,而目前嘗試在論文中實現算法對我來說並不平凡。

因此,以下問題是我面臨的問題。

給定一個二維數組:

[[1 3 4 5 3 3]
 [4 1 4 5 5 2]
 [5 4 3 4 4 2] # pattern
 [4 5 3 4 1 3] # pattern
 [3 3 3 4 4 4] # pattern
 [3 4 3 4 2 5] # pattern
 [4 5 3 4 1 2] # pattern
 [5 1 1 2 4 2]
 [2 1 3 2 1 5]
 [4 4 1 3 3 1]
 [1 4 3 4 4 1]
 [5 2 4 4 4 1]]

和以下示例模式(其中?表示通配符匹配):

[[? ? 3 4 ? ?]
 [? ? 3 4 ? ?]
 [3 3 3 4 4 4]
 [? ? 3 4 ? ?]
 [? ? 3 4 ? ?]]

如何編寫一個包含二維數組和模式的函數,如果模式存在於數組中,則返回True,否則返回False?

如果可能的話,將高度贊賞該問題的通用解決方案,因為我嘗試匹配許多不同的模式。 如果需要,我非常願意提供其他示例。

由於您的搜索空間非常小,因此我們不必通過拆開窗口視圖來擔心內存錯誤。

首先,您需要掩蓋模式存在值的位置

mask

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

然后,你需要什么樣的價值觀是在這些位置的數組:

val = np.array([ 3.,  4.,  3.,  4.,  3.,  3.,  3.,  4.,  4.,  4.,
                 3.,  3.,  3.,  4.,  4.,  4.,  3.,  4.,  3.,  4.])

然后,您需要一個跨輸入的滑動窗口。 最容易使用的實現是skimage.util.view_as_windows但是您可以在此處使用我的純numpy實現

windows = skimage.util.view_as_windows(input, pattern.shape)
# or
windows = window_nd(input, pattern.shape)

現在,通常在這里執行windows[mask]會很危險-如果您卷積許多窗口,它會創建一個巨大的數組。 但是,因為我們在此可以擁有的最多窗戶數是12 * 6 = 72,所以我們不必為此擔心。

loc = np.where(np.all(window[mask] == val, axis = -1))

現在loc是匹配窗口左上角的坐標。

還是應該的。 也許提供一個可以復制/粘貼到解釋器中的測試用例?

此函數采用input_array ,一個pattern和一個函數,可讓您識別通配符。 在這里,我將np.nan用作通配符,但可以是任何東西,因為您可以創建自己的wildcard_function

它適用於任何維數(1或更大)的數組。 我已經為您的示例進行了測試,看起來還可以。

from itertools import product
import numpy as np


def match_pattern(input_array, pattern, wildcard_function=np.isnan):

    pattern_shape = pattern.shape
    input_shape = input_array.shape

    is_wildcard = wildcard_function(pattern) # This gets a boolean N-dim array

    if len(pattern_shape) != len(input_shape):
        raise ValueError("Input array and pattern must have the same dimension")

    shape_difference = [i_s - p_s for i_s, p_s in zip(input_shape, pattern_shape)]

    if any((diff < -1 for diff in shape_difference)):
        raise ValueError("Input array cannot be smaller than pattern in any dimension")

    dimension_iterators = [range(0, s_diff + 1) for s_diff in shape_difference]

    # This loop will iterate over every possible "window" given the shape of the pattern
    for start_indexes in product(*dimension_iterators):
        range_indexes = [slice(start_i, start_i + p_s) for start_i, p_s in zip(start_indexes, pattern_shape)]
        input_match_candidate = input_array[range_indexes]

        # This checks that for the current "window" - the candidate - every element is equal 
        #  to the pattern OR the element in the pattern is a wildcard
        if np.all(
            np.logical_or(
                is_wildcard, (input_match_candidate == pattern)
            )
        ):
            return True

    return False

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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