python 中的矩阵匹配
Matrix match in python
如何在大矩阵中找到最适合小矩阵的"match"?
例如:
small=[[1,2,3],
[4,5,6],
[7,8,9]]
big=[[2,4,2,3,5],
[6,0,1,9,0],
[2,8,2,1,0],
[7,7,4,2,1]]
匹配被定义为矩阵中数字的差异,所以位置 (1,1) 的匹配就好像小矩阵中的数字 5 会在大矩阵中的数字 0 上(所以坐标中小矩阵的中心数字大矩阵的 (1,1)。
位置(1,1)的匹配值为:
m(1,1)=|2−1|+|4−2|+|2−3|+|6−4|+|0−5|+|1−6|+|2−7|+| 8−8|+|2−9|=28
目标是在这些矩阵中找到可能的最小差异。
小矩阵总是有奇数行和列,所以很容易找到它的中心。
手工完成:
small=[[1,2,3],
[4,5,6],
[7,8,9]]
big=[[2,4,2,3,5],
[6,0,1,9,0],
[2,8,2,1,0],
[7,7,4,2,1]]
# collect all the sums
summs= []
# k and j are the offset into big
for k in range(len(big)-len(small)+1):
# add inner list for one row
summs.append([])
for j in range(len(big[0])-len(small[0])+1):
s = 0
for row in range(len(small)):
for col in range(len(small[0])):
s += abs(big[k+row][j+col]-small[row][col])
# add to the inner list
summs[-1].append(s)
print(summs)
输出:
[[28, 29, 38], [24, 31, 39]]
如果您只对较大的坐标感兴趣,请存储 (rowoffset,coloffset,sum)
的元组并且不要将列表装箱到列表中。你可以用 min()
这样的键:
summs = []
for k in range(len(big)-len(small)+1):
for j in range(len(big[0])-len(small[0])+1):
s = 0
for row in range(len(small)):
for col in range(len(small[0])):
s += abs(big[k+row][j+col]-small[row][col])
summs .append( (k,j,s) ) # row,col, sum
print ("Min value for bigger matrix at ", min(summs , key=lambda x:x[2]) )
输出:
Min value for bigger matrix at (1, 0, 24)
如果你有 "draws" 这只会 return 具有最小行、col 偏移量的那个。
另一种可能的解决方案是,返回最小差值和 big
矩阵中的坐标:
small=[[1,2,3],
[4,5,6],
[7,8,9]]
big=[[2,4,2,3,5],
[6,0,1,9,0],
[2,8,2,1,0],
[7,7,4,2,1]]
def difference(small, matrix):
l = len(small)
return sum([abs(small[i][j] - matrix[i][j]) for i in range(l) for j in range(l)])
def getSubmatrices(big, smallLength):
submatrices = []
bigLength = len(big)
step = (bigLength // smallLength) + 1
for i in range(smallLength):
for j in range(step):
tempMatrix = [big[j+k][i:i+smallLength] for k in range(smallLength)]
submatrices.append([i+1,j+1,tempMatrix])
return submatrices
def minDiff(small, big):
submatrices = getSubmatrices(big, len(small))
diffs = [(x,y, difference(small, submatrix)) for x, y, submatrix in submatrices]
minDiff = min(diffs, key=lambda elem: elem[2])
return minDiff
y, x, diff = minDiff(small, big)
print("Minimum difference: ", diff)
print("X = ", x)
print("Y = ", y)
输出:
Minimum difference: 24
X = 1
Y = 2
您可以遍历可行的行和列,并将 big
的切片压缩为 small
以计算差异之和,并使用 min
找到最小值差异:
from itertools import islice
min(
(
sum(
sum(abs(x - y) for x, y in zip(a, b))
for a, b in zip(
(
islice(r, col, col + len(small[0]))
for r in islice(big, row, row + len(small))
),
small
)
),
(row, col)
)
for row in range(len(big) - len(small) + 1)
for col in range(len(big[0]) - len(small[0]) + 1)
)
或一行:
min((sum(sum(abs(x - y) for x, y in zip(a, b)) for a, b in zip((islice(r, col, col + len(small[0])) for r in islice(big, row, row + len(small))), small)), (row, col)) for row in range(len(big) - len(small) + 1) for col in range(len(big[0]) - len(small[0]) + 1))
这个returns:(24, (1, 0))
我会使用 numpy 来帮助解决这个问题。
首先,我会将数组转换为 numpy 数组
import numpy as np
small = np.array([[1,2,3], [4,5,6], [7,8,9]])
big = np.array([[2,4,2,3,5], [6,0,1,9,0], [2,8,2,1,0], [7,7,4,2,1]])
然后我会初始化一个数组来存储测试结果(可选:还有一个字典)
result_shape = np.array(big.shape) - np.array(small.shape) + 1
results = np.zeros((result_shape[0], result_shape[1]))
result_dict = {}
然后遍历小矩阵在大矩阵上可以定位的位置,计算差值:
insert = np.zeros(big.shape)
for i in range(results.shape[0]):
for j in range(results.shape):
insert[i:small.shape[0] + i, j:small.shape[1] + j] = small
results[i, j] = np.sum(np.abs(big - insert)[i:3+i, j:3+j])
# Optional dictionary
result_dict['{}{}'.format(i, j)] = np.sum(np.abs(big - insert)[i:3+i, j:3+j])
那么你可以print(results)
获得:
[[ 28. 29. 38.]
[ 24. 31. 39.]]
and/or因为字典的key中保存了小矩阵在大矩阵上的位置,可以通过key得到小矩阵在大矩阵上的位置差值最小的地方操纵:
pos_min = [int(i) for i in list(min(result_dict, key=result_dict.get))]
如果你 print(pos_min)
,你将获得:
[1, 0]
然后,如果您需要任何内容的索引,您可以根据需要对其进行迭代。希望这对您有所帮助!
如何在大矩阵中找到最适合小矩阵的"match"? 例如:
small=[[1,2,3],
[4,5,6],
[7,8,9]]
big=[[2,4,2,3,5],
[6,0,1,9,0],
[2,8,2,1,0],
[7,7,4,2,1]]
匹配被定义为矩阵中数字的差异,所以位置 (1,1) 的匹配就好像小矩阵中的数字 5 会在大矩阵中的数字 0 上(所以坐标中小矩阵的中心数字大矩阵的 (1,1)。
位置(1,1)的匹配值为: m(1,1)=|2−1|+|4−2|+|2−3|+|6−4|+|0−5|+|1−6|+|2−7|+| 8−8|+|2−9|=28
目标是在这些矩阵中找到可能的最小差异。
小矩阵总是有奇数行和列,所以很容易找到它的中心。
手工完成:
small=[[1,2,3],
[4,5,6],
[7,8,9]]
big=[[2,4,2,3,5],
[6,0,1,9,0],
[2,8,2,1,0],
[7,7,4,2,1]]
# collect all the sums
summs= []
# k and j are the offset into big
for k in range(len(big)-len(small)+1):
# add inner list for one row
summs.append([])
for j in range(len(big[0])-len(small[0])+1):
s = 0
for row in range(len(small)):
for col in range(len(small[0])):
s += abs(big[k+row][j+col]-small[row][col])
# add to the inner list
summs[-1].append(s)
print(summs)
输出:
[[28, 29, 38], [24, 31, 39]]
如果您只对较大的坐标感兴趣,请存储 (rowoffset,coloffset,sum)
的元组并且不要将列表装箱到列表中。你可以用 min()
这样的键:
summs = []
for k in range(len(big)-len(small)+1):
for j in range(len(big[0])-len(small[0])+1):
s = 0
for row in range(len(small)):
for col in range(len(small[0])):
s += abs(big[k+row][j+col]-small[row][col])
summs .append( (k,j,s) ) # row,col, sum
print ("Min value for bigger matrix at ", min(summs , key=lambda x:x[2]) )
输出:
Min value for bigger matrix at (1, 0, 24)
如果你有 "draws" 这只会 return 具有最小行、col 偏移量的那个。
另一种可能的解决方案是,返回最小差值和 big
矩阵中的坐标:
small=[[1,2,3],
[4,5,6],
[7,8,9]]
big=[[2,4,2,3,5],
[6,0,1,9,0],
[2,8,2,1,0],
[7,7,4,2,1]]
def difference(small, matrix):
l = len(small)
return sum([abs(small[i][j] - matrix[i][j]) for i in range(l) for j in range(l)])
def getSubmatrices(big, smallLength):
submatrices = []
bigLength = len(big)
step = (bigLength // smallLength) + 1
for i in range(smallLength):
for j in range(step):
tempMatrix = [big[j+k][i:i+smallLength] for k in range(smallLength)]
submatrices.append([i+1,j+1,tempMatrix])
return submatrices
def minDiff(small, big):
submatrices = getSubmatrices(big, len(small))
diffs = [(x,y, difference(small, submatrix)) for x, y, submatrix in submatrices]
minDiff = min(diffs, key=lambda elem: elem[2])
return minDiff
y, x, diff = minDiff(small, big)
print("Minimum difference: ", diff)
print("X = ", x)
print("Y = ", y)
输出:
Minimum difference: 24
X = 1
Y = 2
您可以遍历可行的行和列,并将 big
的切片压缩为 small
以计算差异之和,并使用 min
找到最小值差异:
from itertools import islice
min(
(
sum(
sum(abs(x - y) for x, y in zip(a, b))
for a, b in zip(
(
islice(r, col, col + len(small[0]))
for r in islice(big, row, row + len(small))
),
small
)
),
(row, col)
)
for row in range(len(big) - len(small) + 1)
for col in range(len(big[0]) - len(small[0]) + 1)
)
或一行:
min((sum(sum(abs(x - y) for x, y in zip(a, b)) for a, b in zip((islice(r, col, col + len(small[0])) for r in islice(big, row, row + len(small))), small)), (row, col)) for row in range(len(big) - len(small) + 1) for col in range(len(big[0]) - len(small[0]) + 1))
这个returns:(24, (1, 0))
我会使用 numpy 来帮助解决这个问题。
首先,我会将数组转换为 numpy 数组
import numpy as np
small = np.array([[1,2,3], [4,5,6], [7,8,9]])
big = np.array([[2,4,2,3,5], [6,0,1,9,0], [2,8,2,1,0], [7,7,4,2,1]])
然后我会初始化一个数组来存储测试结果(可选:还有一个字典)
result_shape = np.array(big.shape) - np.array(small.shape) + 1
results = np.zeros((result_shape[0], result_shape[1]))
result_dict = {}
然后遍历小矩阵在大矩阵上可以定位的位置,计算差值:
insert = np.zeros(big.shape)
for i in range(results.shape[0]):
for j in range(results.shape):
insert[i:small.shape[0] + i, j:small.shape[1] + j] = small
results[i, j] = np.sum(np.abs(big - insert)[i:3+i, j:3+j])
# Optional dictionary
result_dict['{}{}'.format(i, j)] = np.sum(np.abs(big - insert)[i:3+i, j:3+j])
那么你可以print(results)
获得:
[[ 28. 29. 38.]
[ 24. 31. 39.]]
and/or因为字典的key中保存了小矩阵在大矩阵上的位置,可以通过key得到小矩阵在大矩阵上的位置差值最小的地方操纵:
pos_min = [int(i) for i in list(min(result_dict, key=result_dict.get))]
如果你 print(pos_min)
,你将获得:
[1, 0]
然后,如果您需要任何内容的索引,您可以根据需要对其进行迭代。希望这对您有所帮助!