General method to find submatrix in matlab matrix

前端 未结 3 2009
臣服心动
臣服心动 2020-11-29 08:50

I am looking for a \'good\' way to find a matrix (pattern) in a larger matrix (arbitrary number of dimensions).

Example:

total = rand(3,4,5);
sub = t         


        
3条回答
  •  萌比男神i
    2020-11-29 09:33

    This is based on doing all possible shifts of the original matrix total and comparing the upper-leftmost-etc sub-matrix of the shifted total with the sought pattern subs. Shifts are generated using strings, and are applied using circshift.

    Most of the work is done vectorized. Only one level of loops is used.

    The function finds all matchings, not just the first. For example:

    >> total = ones(3,4,5,6);
    >> sub = ones(3,3,5,6);
    >> matrixFind(total, sub)
    ans =
    
         1     1     1     1
         1     2     1     1
    

    Here is the function:

    function sol = matrixFind(total, sub)
    
    nd = ndims(total);
    sizt = size(total).';
    max_sizt = max(sizt);
    sizs = [ size(sub) ones(1,nd-ndims(sub)) ].'; % in case there are
    % trailing singletons
    
    if any(sizs>sizt)
        error('Incorrect dimensions')
    end
    
    allowed_shift = (sizt-sizs);
    max_allowed_shift = max(allowed_shift);
    if max_allowed_shift>0
        shifts = dec2base(0:(max_allowed_shift+1)^nd-1,max_allowed_shift+1).'-'0';
        filter = all(bsxfun(@le,shifts,allowed_shift));
        shifts = shifts(:,filter); % possible shifts of matrix "total", along 
        % all dimensions
    else
        shifts = zeros(nd,1);
    end
    
    for dim = 1:nd
        d{dim} = 1:sizt(dim); % vectors with subindices per dimension
    end
    g = cell(1,nd);
    [g{:}] = ndgrid(d{:}); % grid of subindices per dimension
    gc = cat(nd+1,g{:}); % concatenated grid
    accept = repmat(permute(sizs,[2:nd+1 1]), [sizt; 1]); % acceptable values
    % of subindices in order to compare with matrix "sub"
    ind_filter = find(all(gc<=accept,nd+1));
    
    sol = [];
    for shift = shifts
        total_shifted = circshift(total,-shift);
        if all(total_shifted(ind_filter)==sub(:))
            sol = [ sol; shift.'+1 ];
        end
    end
    

提交回复
热议问题