使用通配符查找多值子矩阵
Finding a multi-value submatrix with wildcards
我有一个包含这些值的矩阵(如果有帮助,这是一个 rgb 图像):
mat = np.array([
[[0, 0, 0], [123, 0, 255], [0, 0, 0]],
[[0, 0, 0], [123, 0, 255], [45, 0, 54]],
[[0, 0, 0], [100, 0, 100], [45, 0, 54]],
])
我正在尝试查找模式的索引位置,例如:
pattern = np.array([
[[123, 0, 255], [*, *, *]],
[[*, *, *], [45, 0, 54],
])
所以在这个例子中,我试图找到 [0, 1] 和 [1, 1] 的坐标。我可以通过简单的嵌套列表迭代来做到这一点,但我正在努力尽快做到这一点,并希望有一些 numpy 方法可以让我有效地做到这一点。
完成此操作的最快方法是什么?
如果答案还允许我指定值范围,则加分,因此我可以查找 [120-125, 0, 255] 而不是查找 [123, 0, 255] 的确切值。
编辑
为了澄清,这里有一个工作示例。我正在寻找一些更快的方法。
mat = np.array([
[[0, 0, 0], [123, 0, 255], [0, 0, 0]],
[[0, 0, 0], [123, 0, 255], [45, 0, 54]],
[[0, 0, 0], [100, 0, 100], [45, 0, 54]],
])
# Look for any any 2x2 sub-matrix such that the upper left pixel is [123, 0, 255]
# and the lower right pixel is [45, 0, 54].
pixels_to_match = [
(0, 0, [123, 0, 255]),
(1, 1, [45, 0, 54]),
]
results = []
for row_ix, row in enumerate(mat):
for col_ix, col in enumerate(row):
view = mat[row_ix:row_ix+2, col_ix:col_ix+2]
found = True
for vals in pixels_to_match:
if not (view[vals[0], vals[1]] == vals[2]).all():
found = False
break
if found:
results.append((row_ix, col_ix))
print(results)
这个怎么样:
from scipy.signal import correlate2d
import numpy as np
mat = np.array([
[[0, 0, 0], [123, 0, 255], [0, 0, 0]],
[[45, 0, 54], [124, 0, 255], [45, 0, 54]],
[[127, 0, 255], [45, 0, 54], [45, 0, 54]],
])
# Find all of the places in the matrix where each condition is satisfied.
cond_1 = np.all(mat >= [120, 0, 255], axis=-1)
cond_1 &= np.all(mat <= [125, 0, 255], axis=-1)
cond_2 = np.all(mat == [45, 0, 54], axis=-1)
# Mark where in the submatrix we want each condition to apply to.
cond_1_map = np.array([[1, 0], [0, 0]])
cond_2_map = np.array([[0, 0], [0, 1]])
# Determine if each condition is in the correct location in the search matrix
matches_1 = correlate2d(cond_1, cond_1_map, mode='same')
matches_2 = correlate2d(cond_2, cond_2_map, mode='same')
matches = matches_1 & matches_2
print("mat:\n", mat)
print("cond_1:\n", cond_1)
print("cond_2:\n", cond_2)
print("matches_1:\n", matches_1)
print("matches_2:\n", matches_2)
print("matches:\n", matches)
首先根据我们的条件将输入数组缩减为二进制数组。然后对于每个条件,我们关联一个单独的子矩阵来表示它在子矩阵中的正确位置。
我们可以使用 correlate2d 来测试条件是否位于原始矩阵中每个索引的正确子矩阵位置。
一旦我们匹配了每个条件,我们就可以将不同的匹配“和”在一起以获得最终值。
mat:
[[[ 0 0 0]
[123 0 255]
[ 0 0 0]]
[[ 45 0 54]
[124 0 255]
[ 45 0 54]]
[[127 0 255]
[ 45 0 54]
[ 45 0 54]]]
cond_1:
[[False True False]
[False True False]
[False False False]]
cond_2:
[[False False False]
[ True False True]
[False True True]]
matches_1:
[[0 1 0]
[0 1 0]
[0 0 0]]
matches_2:
[[0 1 0]
[1 1 0]
[0 0 0]]
matches:
[[0 1 0]
[0 1 0]
[0 0 0]]
我有一个包含这些值的矩阵(如果有帮助,这是一个 rgb 图像):
mat = np.array([
[[0, 0, 0], [123, 0, 255], [0, 0, 0]],
[[0, 0, 0], [123, 0, 255], [45, 0, 54]],
[[0, 0, 0], [100, 0, 100], [45, 0, 54]],
])
我正在尝试查找模式的索引位置,例如:
pattern = np.array([
[[123, 0, 255], [*, *, *]],
[[*, *, *], [45, 0, 54],
])
所以在这个例子中,我试图找到 [0, 1] 和 [1, 1] 的坐标。我可以通过简单的嵌套列表迭代来做到这一点,但我正在努力尽快做到这一点,并希望有一些 numpy 方法可以让我有效地做到这一点。
完成此操作的最快方法是什么?
如果答案还允许我指定值范围,则加分,因此我可以查找 [120-125, 0, 255] 而不是查找 [123, 0, 255] 的确切值。
编辑
为了澄清,这里有一个工作示例。我正在寻找一些更快的方法。
mat = np.array([
[[0, 0, 0], [123, 0, 255], [0, 0, 0]],
[[0, 0, 0], [123, 0, 255], [45, 0, 54]],
[[0, 0, 0], [100, 0, 100], [45, 0, 54]],
])
# Look for any any 2x2 sub-matrix such that the upper left pixel is [123, 0, 255]
# and the lower right pixel is [45, 0, 54].
pixels_to_match = [
(0, 0, [123, 0, 255]),
(1, 1, [45, 0, 54]),
]
results = []
for row_ix, row in enumerate(mat):
for col_ix, col in enumerate(row):
view = mat[row_ix:row_ix+2, col_ix:col_ix+2]
found = True
for vals in pixels_to_match:
if not (view[vals[0], vals[1]] == vals[2]).all():
found = False
break
if found:
results.append((row_ix, col_ix))
print(results)
这个怎么样:
from scipy.signal import correlate2d
import numpy as np
mat = np.array([
[[0, 0, 0], [123, 0, 255], [0, 0, 0]],
[[45, 0, 54], [124, 0, 255], [45, 0, 54]],
[[127, 0, 255], [45, 0, 54], [45, 0, 54]],
])
# Find all of the places in the matrix where each condition is satisfied.
cond_1 = np.all(mat >= [120, 0, 255], axis=-1)
cond_1 &= np.all(mat <= [125, 0, 255], axis=-1)
cond_2 = np.all(mat == [45, 0, 54], axis=-1)
# Mark where in the submatrix we want each condition to apply to.
cond_1_map = np.array([[1, 0], [0, 0]])
cond_2_map = np.array([[0, 0], [0, 1]])
# Determine if each condition is in the correct location in the search matrix
matches_1 = correlate2d(cond_1, cond_1_map, mode='same')
matches_2 = correlate2d(cond_2, cond_2_map, mode='same')
matches = matches_1 & matches_2
print("mat:\n", mat)
print("cond_1:\n", cond_1)
print("cond_2:\n", cond_2)
print("matches_1:\n", matches_1)
print("matches_2:\n", matches_2)
print("matches:\n", matches)
首先根据我们的条件将输入数组缩减为二进制数组。然后对于每个条件,我们关联一个单独的子矩阵来表示它在子矩阵中的正确位置。
我们可以使用 correlate2d 来测试条件是否位于原始矩阵中每个索引的正确子矩阵位置。
一旦我们匹配了每个条件,我们就可以将不同的匹配“和”在一起以获得最终值。
mat:
[[[ 0 0 0]
[123 0 255]
[ 0 0 0]]
[[ 45 0 54]
[124 0 255]
[ 45 0 54]]
[[127 0 255]
[ 45 0 54]
[ 45 0 54]]]
cond_1:
[[False True False]
[False True False]
[False False False]]
cond_2:
[[False False False]
[ True False True]
[False True True]]
matches_1:
[[0 1 0]
[0 1 0]
[0 0 0]]
matches_2:
[[0 1 0]
[1 1 0]
[0 0 0]]
matches:
[[0 1 0]
[0 1 0]
[0 0 0]]