Matlab 查找矩阵中水平或垂直放置的向量

Matlab 查找矩阵中水平或垂直放置的向量,matlab,matrix,vector,match,Matlab,Matrix,Vector,Match,我试图在一个大矩阵a中找到一个向量B B可以是A的多行一列,也可以是A的多列一行 例如: A = [56 55 53 52 53; 49 45 44 45 47; 33 30 31 34 35; 34 34 27 24 26; 44 48 45 35 24; 56 57 57 53 39; 62 62 62 60 55; 62 61 61 54 47;

我试图在一个大矩阵
a
中找到一个向量
B

B
可以是
A
的多行一列,也可以是
A
的多列一行

例如:

A = [56  55  53  52  53;
     49  45  44  45  47;
     33  30  31  34  35;
     34  34  27  24  26;
     44  48  45  35  24;
     56  57  57  53  39;
     62  62  62  60  55;
     62  61  61  54  47;
     49  47  42  40  32;
     47  42  44  45  40];

B = [34 27 24];
我需要一个返回行和列索引的函数,例如:
查找(A,B)→ 第4行,第2列至第4列(对于给定示例)


如何执行此操作?

对于固定大小的
B
,可以使用以下方法:

[row, col] = find(A(:, 1:end-2) == B(1) & ...
                  A(:, 2:end-1) == B(2) & ...
                  A(:, 3:end) == B(3))
这将返回
row=4
col=2
,即
A
B(1)
的位置

有关更多信息,请参阅

这可以使用for循环扩展到变量大小向量
B

Ah = true(size(A) - [0 length(B)-1]);
for i=1:length(B)
    Ah= Ah & A(:, i:end-length(B)+i) == B(i);
end
[row, col] = find(Ah);
这可以很容易地进行扩展,以找到水平和垂直出现的
B
,如下所示:

Ah = true(size(A) - [0 length(B)-1]);
Av = true(size(A) - [length(B)-1 0]);
for i=1:length(B)
    Ah= Ah & A(:, i:end-3+i) == B(i);
    Av= Av & A(i:end-3+i, :) == B(i);
end
[row_h, col_h] = find(Ah);
[row_v, col_v] = find(Av);
基准


请注意,尽管如此,我使用的是for循环,这种方法比rahnema1的解决方案更快,特别是当您只对水平(或垂直)匹配感兴趣时。查看以了解更多信息。

对于固定大小的
B
,可以使用以下方法:

[row, col] = find(A(:, 1:end-2) == B(1) & ...
                  A(:, 2:end-1) == B(2) & ...
                  A(:, 3:end) == B(3))
这将返回
row=4
col=2
,即
A
B(1)
的位置

有关更多信息,请参阅

这可以使用for循环扩展到变量大小向量
B

Ah = true(size(A) - [0 length(B)-1]);
for i=1:length(B)
    Ah= Ah & A(:, i:end-length(B)+i) == B(i);
end
[row, col] = find(Ah);
这可以很容易地进行扩展,以找到水平和垂直出现的
B
,如下所示:

Ah = true(size(A) - [0 length(B)-1]);
Av = true(size(A) - [length(B)-1 0]);
for i=1:length(B)
    Ah= Ah & A(:, i:end-3+i) == B(i);
    Av= Av & A(i:end-3+i, :) == B(i);
end
[row_h, col_h] = find(Ah);
[row_v, col_v] = find(Av);
基准

请注意,尽管如此,我使用的是for循环,这种方法比rahnema1的解决方案更快,特别是当您只对水平(或垂直)匹配感兴趣时。查看以获取更多信息。

我们可以将矩阵设置为
char
,并用于搜索矩阵:

%Horizontal search
A_str_h = typecast(A.','char');
B_str = typecast(B,'char');
charsize = numel(B_str)/numel(B);
pos_h = strfind(A_str_h,B_str)-1;
pos_h = pos_h(mod(pos_h,charsize)==0)/charsize+1;
[col_h row_h] = ind2sub(flip(size(A)),pos_h);
idx_h = col_h <= (size(A,2)-numel(B)+1);
row_h = row_h(idx_h);
col_h = col_h(idx_h);

%Vertical search
A_str_v = typecast(A,'char');
B_str = typecast(B,'char');
charsize = numel(B_str)/numel(B);
pos_v = strfind(A_str_v,B_str)-1;
pos_v = pos_v(mod(pos_v,charsize)==0)/charsize+1;
[row_v col_v] = ind2sub(size(A),pos_v);
idx_v = row_v <= (size(A,1)-numel(B)+1);
row_v = row_v(idx_v);
col_v = col_v(idx_v);
[xh-yh]
表示水平匹配的起始位置,
[xv-yv]
表示垂直匹配的起始位置

以下是将
A
设置为
[2750*1250]
矩阵和
B
的不同大小的不同方法的测试结果:

结果表明,与其他方法相比,
CONVN
的效率较低,不适用于大尺寸的阵列,
STRFIND
对所有阵列尺寸的效果最好

*方法在倍频程中进行测试。

我们可以将矩阵转换为
char
,并用于搜索矩阵:

%Horizontal search
A_str_h = typecast(A.','char');
B_str = typecast(B,'char');
charsize = numel(B_str)/numel(B);
pos_h = strfind(A_str_h,B_str)-1;
pos_h = pos_h(mod(pos_h,charsize)==0)/charsize+1;
[col_h row_h] = ind2sub(flip(size(A)),pos_h);
idx_h = col_h <= (size(A,2)-numel(B)+1);
row_h = row_h(idx_h);
col_h = col_h(idx_h);

%Vertical search
A_str_v = typecast(A,'char');
B_str = typecast(B,'char');
charsize = numel(B_str)/numel(B);
pos_v = strfind(A_str_v,B_str)-1;
pos_v = pos_v(mod(pos_v,charsize)==0)/charsize+1;
[row_v col_v] = ind2sub(size(A),pos_v);
idx_v = row_v <= (size(A,1)-numel(B)+1);
row_v = row_v(idx_v);
col_v = col_v(idx_v);
[xh-yh]
表示水平匹配的起始位置,
[xv-yv]
表示垂直匹配的起始位置

以下是将
A
设置为
[2750*1250]
矩阵和
B
的不同大小的不同方法的测试结果:

结果表明,与其他方法相比,
CONVN
的效率较低,不适用于大尺寸的阵列,
STRFIND
对所有阵列尺寸的效果最好

*方法在rahnema1和m7913d之间的倍频程中进行测试。

基准 水平和垂直匹配

使用
timeit
对给定示例(小A)和
100^2
较大示例(大A)的rahnema1和m7913d解决方案进行基准测试,得出以下结果:

Method   | Small A    | Large A
--------------------------------
rahnema1 | 4.0416e-05 | 0.0187
m7913d   | 2.5242e-05 | 0.0129
请注意,m7913d的解决方案快了约50%

水平(或垂直)仅匹配

如果您只对水平匹配感兴趣,将获得以下结果:

Method   | Small A    | Large A
--------------------------------
rahnema1 | 9.6752e-06 | 0.0115
m7913d   | 5.8634e-06 | 0.0056
在这种情况下,m7913d的解决方案更为有利,速度快了约100%

完整的基准代码

A=[56  55  53  52  53;
  49  45  44  45  47;
  33  30  31  34  35;
  34  34  27  24  26;
  44  48  45  35  24;
  56  57  57  53  39;
  62  62  62  60  55;
  62  61  61  54  47;
  49  47  42  40  32;
  47  42  44  45  40];
B=[34 27 24];
A_large = repmat(A, 100, 100);

t_m7913d = timeit(@() m7913d(A, B))
t_rahnema = timeit(@() rahnema1(A, B))

t_large_m7913d = timeit(@() m7913d(A_large, B))
t_large_rahnema = timeit(@() rahnema1(A_large, B))

 function [row_h, col_h, row_v, col_v] = m7913d(A, B)
    Ah = true(size(A) - [0 length(B)-1]);
    Av = true(size(A) - [length(B)-1 0]);
    for i=1:length(B)
        Ah= Ah & A(:, i:end-3+i) == B(i);
        Av= Av & A(i:end-3+i, :) == B(i);
    end
    [row_h, col_h] = find(Ah);
    [row_v, col_v] = find(Av);
end

function [row_h, col_h, row_v, col_v] = rahnema1(A, B) 
    n = numel(B);
    C = A == reshape(B,1,1,n);
    mask_h = permute(eye(n),[3 2 1]);
    mask_v = permute(eye(n),[1 3 2]);
    [row_h, col_h]=find(convn(C,mask_h,'valid')==n);
    [row_v, col_v]=find(convn(C,mask_v,'valid')==n);
end
rahnema1和m7913d之间的基准 水平和垂直匹配

使用
timeit
对给定示例(小A)和
100^2
较大示例(大A)的rahnema1和m7913d解决方案进行基准测试,得出以下结果:

Method   | Small A    | Large A
--------------------------------
rahnema1 | 4.0416e-05 | 0.0187
m7913d   | 2.5242e-05 | 0.0129
请注意,m7913d的解决方案快了约50%

水平(或垂直)仅匹配

如果您只对水平匹配感兴趣,将获得以下结果:

Method   | Small A    | Large A
--------------------------------
rahnema1 | 9.6752e-06 | 0.0115
m7913d   | 5.8634e-06 | 0.0056
在这种情况下,m7913d的解决方案更为有利,速度快了约100%

完整的基准代码

A=[56  55  53  52  53;
  49  45  44  45  47;
  33  30  31  34  35;
  34  34  27  24  26;
  44  48  45  35  24;
  56  57  57  53  39;
  62  62  62  60  55;
  62  61  61  54  47;
  49  47  42  40  32;
  47  42  44  45  40];
B=[34 27 24];
A_large = repmat(A, 100, 100);

t_m7913d = timeit(@() m7913d(A, B))
t_rahnema = timeit(@() rahnema1(A, B))

t_large_m7913d = timeit(@() m7913d(A_large, B))
t_large_rahnema = timeit(@() rahnema1(A_large, B))

 function [row_h, col_h, row_v, col_v] = m7913d(A, B)
    Ah = true(size(A) - [0 length(B)-1]);
    Av = true(size(A) - [length(B)-1 0]);
    for i=1:length(B)
        Ah= Ah & A(:, i:end-3+i) == B(i);
        Av= Av & A(i:end-3+i, :) == B(i);
    end
    [row_h, col_h] = find(Ah);
    [row_v, col_v] = find(Av);
end

function [row_h, col_h, row_v, col_v] = rahnema1(A, B) 
    n = numel(B);
    C = A == reshape(B,1,1,n);
    mask_h = permute(eye(n),[3 2 1]);
    mask_v = permute(eye(n),[1 3 2]);
    [row_h, col_h]=find(convn(C,mask_h,'valid')==n);
    [row_v, col_v]=find(convn(C,mask_v,'valid')==n);
end