- Match occurs if all(abs(Ax-B)<0.1) (probably what you want?)
- Match occurs if all(rms(Ax-B)<0.1)
- Match occurs if mean2(Ax-B)<0.1
- Match occurs if sum(Ax-B)<0.1
Find matrix inside larger matrix with tolerance
1 view (last 30 days)
Show older comments
How can I write a script to find a smaller matrix B inside a larger matrix A with a specified tolerance and return the index/indices where B starts in A? For example, with a tolerance of 0.1:
A =
8 1 4 8 8 5
8 3 10 2 3 10
4 1 1 5 7 4
7 1 5 5 7 6
2 9 4 7 2 3
8 7 8 8 2 8
B =
0.9 1.1 5
1.1 5 4.9
9 3.9 7.1
index = (2,3)
1 Comment
DGM
on 21 Jun 2021
Edited: DGM
on 21 Jun 2021
You'll need to define your testing criteria before a tolerance metric has meaning. A tolerance of 0.1 might mean any number of things depending on what the goal was. Consider the matrix B and the corresponding region in A at any given point during evaluation (Ax)
Depending on how loose your requirements are, you may simply be able to use normxcorr2() if you just want to find the closest, if inexact match.
A logical filter as described above could otherwise be implemented using nlfilter() and a user-defined function to make the comparison. That said, if it's something you need to use often, you might find nlfilter() to be inconveniently slow. Replacing it with a simple sliding window routine is often faster.
Accepted Answer
DGM
on 21 Jun 2021
As I mentioned, you can do this with nlfilter()
A = [8 1 4 8 8 5;
8 3 10 2 3 10;
4 1 1 5 7 4;
7 1 5 5 7 6;
2 9 4 7 2 3;
8 7 8 8 2 8];
B = [0.9 1.1 5;
1.1 5 4.9;
9 3.9 7.1];
tol = 0.1;
% use nlfilter()
F = @(x) all(abs(x-B)<=(tol+eps),'all');
map = nlfilter(A,size(B),F) % logical map of matches
[row col] = find(map) % if you really want subscripts instead
% can't run nlfilter() in the browser, so there are no example outputs here
Or you could just do the same process without nlfilter()
filtsize = size(B);
s0 = size(A);
padsize = floor(filtsize/2);
% nlfilter() uses zero-padding, but you could replicate, etc
A = padarray(A,padsize,0,'both');
s = size(A);
matches = false(s0);
osm = filtsize(1)-1;
osn = filtsize(2)-1;
for n = 1:(s(2)-2*padsize(2))
for m = 1:(s(1)-2*padsize(1))
sample = A(m:(m+osm),n:(n+osn));
matches(m,n) = all(abs(sample-B)<=(tol+eps),'all');
end
end
matches % logical map of matches
[row col] = find(matches) % if you really want subscripts instead
0 Comments
More Answers (0)
See Also
Categories
Find more on 2-D and 3-D Plots in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!