Matrix match in python
How can I find the best "match" for small matrix in big matrix?
For example:
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]]
The match is defined as difference of numbers in matrix, so match in position (1,1) is as if number 5 from small would be on number 0 from big matrix (so the central number from small matrix in coordinates (1,1) of big matrix.
The match value in position (1,1) is:
m(1,1)=|2−1|+|4−2|+|2−3|+|6−4|+|0−5|+|1−6|+|2−7|+|8−8|+|2−9|=28
The goal is to find the lowest difference posible in those matrixes.
The small matrix always has odd number of lines and columns, so it's easy to find it's centre.
python python-3.x matrix similarity
add a comment |
How can I find the best "match" for small matrix in big matrix?
For example:
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]]
The match is defined as difference of numbers in matrix, so match in position (1,1) is as if number 5 from small would be on number 0 from big matrix (so the central number from small matrix in coordinates (1,1) of big matrix.
The match value in position (1,1) is:
m(1,1)=|2−1|+|4−2|+|2−3|+|6−4|+|0−5|+|1−6|+|2−7|+|8−8|+|2−9|=28
The goal is to find the lowest difference posible in those matrixes.
The small matrix always has odd number of lines and columns, so it's easy to find it's centre.
python python-3.x matrix similarity
1
Such template matching almost certainly exists in opencv already.
– wim
Nov 13 '18 at 18:23
nicely described - where is what you coded to try to solve that?
– Patrick Artner
Nov 13 '18 at 18:28
4
Please do not vandalize your posts. By posting on the Stack Exchange network, you've granted a non-revocable right for SE to distribute that content (under the CC BY-SA 3.0 license). By SE policy, any vandalism will be reverted.
– FrankerZ
Nov 19 '18 at 18:12
add a comment |
How can I find the best "match" for small matrix in big matrix?
For example:
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]]
The match is defined as difference of numbers in matrix, so match in position (1,1) is as if number 5 from small would be on number 0 from big matrix (so the central number from small matrix in coordinates (1,1) of big matrix.
The match value in position (1,1) is:
m(1,1)=|2−1|+|4−2|+|2−3|+|6−4|+|0−5|+|1−6|+|2−7|+|8−8|+|2−9|=28
The goal is to find the lowest difference posible in those matrixes.
The small matrix always has odd number of lines and columns, so it's easy to find it's centre.
python python-3.x matrix similarity
How can I find the best "match" for small matrix in big matrix?
For example:
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]]
The match is defined as difference of numbers in matrix, so match in position (1,1) is as if number 5 from small would be on number 0 from big matrix (so the central number from small matrix in coordinates (1,1) of big matrix.
The match value in position (1,1) is:
m(1,1)=|2−1|+|4−2|+|2−3|+|6−4|+|0−5|+|1−6|+|2−7|+|8−8|+|2−9|=28
The goal is to find the lowest difference posible in those matrixes.
The small matrix always has odd number of lines and columns, so it's easy to find it's centre.
python python-3.x matrix similarity
python python-3.x matrix similarity
edited Nov 26 '18 at 15:31
IHav
asked Nov 13 '18 at 18:20
IHavIHav
575
575
1
Such template matching almost certainly exists in opencv already.
– wim
Nov 13 '18 at 18:23
nicely described - where is what you coded to try to solve that?
– Patrick Artner
Nov 13 '18 at 18:28
4
Please do not vandalize your posts. By posting on the Stack Exchange network, you've granted a non-revocable right for SE to distribute that content (under the CC BY-SA 3.0 license). By SE policy, any vandalism will be reverted.
– FrankerZ
Nov 19 '18 at 18:12
add a comment |
1
Such template matching almost certainly exists in opencv already.
– wim
Nov 13 '18 at 18:23
nicely described - where is what you coded to try to solve that?
– Patrick Artner
Nov 13 '18 at 18:28
4
Please do not vandalize your posts. By posting on the Stack Exchange network, you've granted a non-revocable right for SE to distribute that content (under the CC BY-SA 3.0 license). By SE policy, any vandalism will be reverted.
– FrankerZ
Nov 19 '18 at 18:12
1
1
Such template matching almost certainly exists in opencv already.
– wim
Nov 13 '18 at 18:23
Such template matching almost certainly exists in opencv already.
– wim
Nov 13 '18 at 18:23
nicely described - where is what you coded to try to solve that?
– Patrick Artner
Nov 13 '18 at 18:28
nicely described - where is what you coded to try to solve that?
– Patrick Artner
Nov 13 '18 at 18:28
4
4
Please do not vandalize your posts. By posting on the Stack Exchange network, you've granted a non-revocable right for SE to distribute that content (under the CC BY-SA 3.0 license). By SE policy, any vandalism will be reverted.
– FrankerZ
Nov 19 '18 at 18:12
Please do not vandalize your posts. By posting on the Stack Exchange network, you've granted a non-revocable right for SE to distribute that content (under the CC BY-SA 3.0 license). By SE policy, any vandalism will be reverted.
– FrankerZ
Nov 19 '18 at 18:12
add a comment |
4 Answers
4
active
oldest
votes
You can iterate through the viable rows and columns and zip the slices of big
with small
to calculate the sum of differences, and use min
to find the minimum among the differences:
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)
)
or in one line:
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))
This returns: (24, (1, 0))
pylint: line too long.
– Muhammad Ahmad
Nov 13 '18 at 19:16
I've updated the answer with a broken down version then.
– blhsing
Nov 13 '18 at 19:21
Like your solution! Although having some issues: for matrix
– IHav
Nov 13 '18 at 21:59
1
@IvanHlivan I see. I've put your sample data here: repl.it/repls/FrontFoolhardyExtraction and as you can see (by clicking on the Run button), the smallest difference does occur at (0, 16). How did you come to the conclusion that it should be (5, x)? And what is this "x" in (5, x) anyway?
– blhsing
Nov 13 '18 at 22:22
1
Sorry, my fault. Compared other results.
– IHav
Nov 13 '18 at 23:18
|
show 2 more comments
Done by hand:
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)
Output:
[[28, 29, 38], [24, 31, 39]]
If you are just interested in the coords in the bigger one, store tuples of (rowoffset,coloffset,sum)
and dont box lists into lists. You can use min()
with a key that way:
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]) )
Output:
Min value for bigger matrix at (1, 0, 24)
If you had "draws" this would only return the one with minimal row, col offset.
add a comment |
Another possible solution would be this, returning the minimum difference and the coordinates in the big
matrix:
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)
Output:
Minimum difference: 24
X = 1
Y = 2
add a comment |
I would use numpy to help with this.
To start I would convert the arrays to numpy arrays
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]])
then I would initialize an array to store the results of the test (optional: a dictionary as well)
result_shape = np.array(big.shape) - np.array(small.shape) + 1
results = np.zeros((result_shape[0], result_shape[1]))
result_dict = {}
Then iterate over the positions in which the small matrix can be positioned over the large matrix and calculate the difference:
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])
Then you can print(results)
and obtain:
[[ 28. 29. 38.]
[ 24. 31. 39.]]
and/or because the position of the small matrix over the big matrix is stored in the keys of the dictionary, you can get the position of the small matrix over the large matrix where the difference is smallest by key manipulation:
pos_min = [int(i) for i in list(min(result_dict, key=result_dict.get))]
and if you print(pos_min)
, you obtain:
[1, 0]
then if you need the index for anything you can iterate over it if required. Hope this helps!
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53287262%2fmatrix-match-in-python%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
4 Answers
4
active
oldest
votes
4 Answers
4
active
oldest
votes
active
oldest
votes
active
oldest
votes
You can iterate through the viable rows and columns and zip the slices of big
with small
to calculate the sum of differences, and use min
to find the minimum among the differences:
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)
)
or in one line:
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))
This returns: (24, (1, 0))
pylint: line too long.
– Muhammad Ahmad
Nov 13 '18 at 19:16
I've updated the answer with a broken down version then.
– blhsing
Nov 13 '18 at 19:21
Like your solution! Although having some issues: for matrix
– IHav
Nov 13 '18 at 21:59
1
@IvanHlivan I see. I've put your sample data here: repl.it/repls/FrontFoolhardyExtraction and as you can see (by clicking on the Run button), the smallest difference does occur at (0, 16). How did you come to the conclusion that it should be (5, x)? And what is this "x" in (5, x) anyway?
– blhsing
Nov 13 '18 at 22:22
1
Sorry, my fault. Compared other results.
– IHav
Nov 13 '18 at 23:18
|
show 2 more comments
You can iterate through the viable rows and columns and zip the slices of big
with small
to calculate the sum of differences, and use min
to find the minimum among the differences:
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)
)
or in one line:
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))
This returns: (24, (1, 0))
pylint: line too long.
– Muhammad Ahmad
Nov 13 '18 at 19:16
I've updated the answer with a broken down version then.
– blhsing
Nov 13 '18 at 19:21
Like your solution! Although having some issues: for matrix
– IHav
Nov 13 '18 at 21:59
1
@IvanHlivan I see. I've put your sample data here: repl.it/repls/FrontFoolhardyExtraction and as you can see (by clicking on the Run button), the smallest difference does occur at (0, 16). How did you come to the conclusion that it should be (5, x)? And what is this "x" in (5, x) anyway?
– blhsing
Nov 13 '18 at 22:22
1
Sorry, my fault. Compared other results.
– IHav
Nov 13 '18 at 23:18
|
show 2 more comments
You can iterate through the viable rows and columns and zip the slices of big
with small
to calculate the sum of differences, and use min
to find the minimum among the differences:
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)
)
or in one line:
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))
This returns: (24, (1, 0))
You can iterate through the viable rows and columns and zip the slices of big
with small
to calculate the sum of differences, and use min
to find the minimum among the differences:
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)
)
or in one line:
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))
This returns: (24, (1, 0))
edited Nov 13 '18 at 22:03
answered Nov 13 '18 at 19:06
blhsingblhsing
29.5k41336
29.5k41336
pylint: line too long.
– Muhammad Ahmad
Nov 13 '18 at 19:16
I've updated the answer with a broken down version then.
– blhsing
Nov 13 '18 at 19:21
Like your solution! Although having some issues: for matrix
– IHav
Nov 13 '18 at 21:59
1
@IvanHlivan I see. I've put your sample data here: repl.it/repls/FrontFoolhardyExtraction and as you can see (by clicking on the Run button), the smallest difference does occur at (0, 16). How did you come to the conclusion that it should be (5, x)? And what is this "x" in (5, x) anyway?
– blhsing
Nov 13 '18 at 22:22
1
Sorry, my fault. Compared other results.
– IHav
Nov 13 '18 at 23:18
|
show 2 more comments
pylint: line too long.
– Muhammad Ahmad
Nov 13 '18 at 19:16
I've updated the answer with a broken down version then.
– blhsing
Nov 13 '18 at 19:21
Like your solution! Although having some issues: for matrix
– IHav
Nov 13 '18 at 21:59
1
@IvanHlivan I see. I've put your sample data here: repl.it/repls/FrontFoolhardyExtraction and as you can see (by clicking on the Run button), the smallest difference does occur at (0, 16). How did you come to the conclusion that it should be (5, x)? And what is this "x" in (5, x) anyway?
– blhsing
Nov 13 '18 at 22:22
1
Sorry, my fault. Compared other results.
– IHav
Nov 13 '18 at 23:18
pylint: line too long.
– Muhammad Ahmad
Nov 13 '18 at 19:16
pylint: line too long.
– Muhammad Ahmad
Nov 13 '18 at 19:16
I've updated the answer with a broken down version then.
– blhsing
Nov 13 '18 at 19:21
I've updated the answer with a broken down version then.
– blhsing
Nov 13 '18 at 19:21
Like your solution! Although having some issues: for matrix
– IHav
Nov 13 '18 at 21:59
Like your solution! Although having some issues: for matrix
– IHav
Nov 13 '18 at 21:59
1
1
@IvanHlivan I see. I've put your sample data here: repl.it/repls/FrontFoolhardyExtraction and as you can see (by clicking on the Run button), the smallest difference does occur at (0, 16). How did you come to the conclusion that it should be (5, x)? And what is this "x" in (5, x) anyway?
– blhsing
Nov 13 '18 at 22:22
@IvanHlivan I see. I've put your sample data here: repl.it/repls/FrontFoolhardyExtraction and as you can see (by clicking on the Run button), the smallest difference does occur at (0, 16). How did you come to the conclusion that it should be (5, x)? And what is this "x" in (5, x) anyway?
– blhsing
Nov 13 '18 at 22:22
1
1
Sorry, my fault. Compared other results.
– IHav
Nov 13 '18 at 23:18
Sorry, my fault. Compared other results.
– IHav
Nov 13 '18 at 23:18
|
show 2 more comments
Done by hand:
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)
Output:
[[28, 29, 38], [24, 31, 39]]
If you are just interested in the coords in the bigger one, store tuples of (rowoffset,coloffset,sum)
and dont box lists into lists. You can use min()
with a key that way:
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]) )
Output:
Min value for bigger matrix at (1, 0, 24)
If you had "draws" this would only return the one with minimal row, col offset.
add a comment |
Done by hand:
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)
Output:
[[28, 29, 38], [24, 31, 39]]
If you are just interested in the coords in the bigger one, store tuples of (rowoffset,coloffset,sum)
and dont box lists into lists. You can use min()
with a key that way:
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]) )
Output:
Min value for bigger matrix at (1, 0, 24)
If you had "draws" this would only return the one with minimal row, col offset.
add a comment |
Done by hand:
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)
Output:
[[28, 29, 38], [24, 31, 39]]
If you are just interested in the coords in the bigger one, store tuples of (rowoffset,coloffset,sum)
and dont box lists into lists. You can use min()
with a key that way:
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]) )
Output:
Min value for bigger matrix at (1, 0, 24)
If you had "draws" this would only return the one with minimal row, col offset.
Done by hand:
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)
Output:
[[28, 29, 38], [24, 31, 39]]
If you are just interested in the coords in the bigger one, store tuples of (rowoffset,coloffset,sum)
and dont box lists into lists. You can use min()
with a key that way:
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]) )
Output:
Min value for bigger matrix at (1, 0, 24)
If you had "draws" this would only return the one with minimal row, col offset.
edited Nov 13 '18 at 18:48
answered Nov 13 '18 at 18:40
Patrick ArtnerPatrick Artner
22.9k62243
22.9k62243
add a comment |
add a comment |
Another possible solution would be this, returning the minimum difference and the coordinates in the big
matrix:
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)
Output:
Minimum difference: 24
X = 1
Y = 2
add a comment |
Another possible solution would be this, returning the minimum difference and the coordinates in the big
matrix:
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)
Output:
Minimum difference: 24
X = 1
Y = 2
add a comment |
Another possible solution would be this, returning the minimum difference and the coordinates in the big
matrix:
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)
Output:
Minimum difference: 24
X = 1
Y = 2
Another possible solution would be this, returning the minimum difference and the coordinates in the big
matrix:
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)
Output:
Minimum difference: 24
X = 1
Y = 2
edited Nov 13 '18 at 18:57
answered Nov 13 '18 at 18:52
Vasilis G.Vasilis G.
3,4642722
3,4642722
add a comment |
add a comment |
I would use numpy to help with this.
To start I would convert the arrays to numpy arrays
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]])
then I would initialize an array to store the results of the test (optional: a dictionary as well)
result_shape = np.array(big.shape) - np.array(small.shape) + 1
results = np.zeros((result_shape[0], result_shape[1]))
result_dict = {}
Then iterate over the positions in which the small matrix can be positioned over the large matrix and calculate the difference:
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])
Then you can print(results)
and obtain:
[[ 28. 29. 38.]
[ 24. 31. 39.]]
and/or because the position of the small matrix over the big matrix is stored in the keys of the dictionary, you can get the position of the small matrix over the large matrix where the difference is smallest by key manipulation:
pos_min = [int(i) for i in list(min(result_dict, key=result_dict.get))]
and if you print(pos_min)
, you obtain:
[1, 0]
then if you need the index for anything you can iterate over it if required. Hope this helps!
add a comment |
I would use numpy to help with this.
To start I would convert the arrays to numpy arrays
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]])
then I would initialize an array to store the results of the test (optional: a dictionary as well)
result_shape = np.array(big.shape) - np.array(small.shape) + 1
results = np.zeros((result_shape[0], result_shape[1]))
result_dict = {}
Then iterate over the positions in which the small matrix can be positioned over the large matrix and calculate the difference:
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])
Then you can print(results)
and obtain:
[[ 28. 29. 38.]
[ 24. 31. 39.]]
and/or because the position of the small matrix over the big matrix is stored in the keys of the dictionary, you can get the position of the small matrix over the large matrix where the difference is smallest by key manipulation:
pos_min = [int(i) for i in list(min(result_dict, key=result_dict.get))]
and if you print(pos_min)
, you obtain:
[1, 0]
then if you need the index for anything you can iterate over it if required. Hope this helps!
add a comment |
I would use numpy to help with this.
To start I would convert the arrays to numpy arrays
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]])
then I would initialize an array to store the results of the test (optional: a dictionary as well)
result_shape = np.array(big.shape) - np.array(small.shape) + 1
results = np.zeros((result_shape[0], result_shape[1]))
result_dict = {}
Then iterate over the positions in which the small matrix can be positioned over the large matrix and calculate the difference:
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])
Then you can print(results)
and obtain:
[[ 28. 29. 38.]
[ 24. 31. 39.]]
and/or because the position of the small matrix over the big matrix is stored in the keys of the dictionary, you can get the position of the small matrix over the large matrix where the difference is smallest by key manipulation:
pos_min = [int(i) for i in list(min(result_dict, key=result_dict.get))]
and if you print(pos_min)
, you obtain:
[1, 0]
then if you need the index for anything you can iterate over it if required. Hope this helps!
I would use numpy to help with this.
To start I would convert the arrays to numpy arrays
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]])
then I would initialize an array to store the results of the test (optional: a dictionary as well)
result_shape = np.array(big.shape) - np.array(small.shape) + 1
results = np.zeros((result_shape[0], result_shape[1]))
result_dict = {}
Then iterate over the positions in which the small matrix can be positioned over the large matrix and calculate the difference:
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])
Then you can print(results)
and obtain:
[[ 28. 29. 38.]
[ 24. 31. 39.]]
and/or because the position of the small matrix over the big matrix is stored in the keys of the dictionary, you can get the position of the small matrix over the large matrix where the difference is smallest by key manipulation:
pos_min = [int(i) for i in list(min(result_dict, key=result_dict.get))]
and if you print(pos_min)
, you obtain:
[1, 0]
then if you need the index for anything you can iterate over it if required. Hope this helps!
edited Nov 13 '18 at 20:21
answered Nov 13 '18 at 19:53
J.AlukoJ.Aluko
163
163
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53287262%2fmatrix-match-in-python%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
1
Such template matching almost certainly exists in opencv already.
– wim
Nov 13 '18 at 18:23
nicely described - where is what you coded to try to solve that?
– Patrick Artner
Nov 13 '18 at 18:28
4
Please do not vandalize your posts. By posting on the Stack Exchange network, you've granted a non-revocable right for SE to distribute that content (under the CC BY-SA 3.0 license). By SE policy, any vandalism will be reverted.
– FrankerZ
Nov 19 '18 at 18:12