フィルターのクリア

Find matrix inside larger matrix with tolerance

2 ビュー (過去 30 日間)
Richard Batelaan
Richard Batelaan 2021 年 6 月 21 日
回答済み: DGM 2021 年 6 月 21 日
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 件のコメント
DGM
DGM 2021 年 6 月 21 日
編集済み: DGM 2021 年 6 月 21 日
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)
  • 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
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.

サインインしてコメントする。

採用された回答

DGM
DGM 2021 年 6 月 21 日
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
matches = 6×6 logical array
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
[row col] = find(matches) % if you really want subscripts instead
row = 4
col = 3

その他の回答 (0 件)

カテゴリ

Help Center および File ExchangeMultidimensional Arrays についてさらに検索

タグ

製品


リリース

R2019a

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by