Преместване на малка матрица вътре в по-голяма матрица в MATLAB

Да приемем, че A е 5x5 матрица от нули:

>> A = zeros(5)

A =

     0     0     0     0     0
     0     0     0     0     0
     0     0     0     0     0
     0     0     0     0     0
     0     0     0     0     0

И B е малка матрица от единици (2x2):

>> B = ones(2)

B =

     1     1
     1     1

Сега търся 16 различни случая, които представляват матрици от C1, C2, C3, ..., C16

Които са:

C1 =                                

     1     1     0     0     0
     1     1     0     0     0
     0     0     0     0     0
     0     0     0     0     0
     0     0     0     0     0

C2 =                                

     0     0     0     0     0
     1     1     0     0     0
     1     1     0     0     0
     0     0     0     0     0
     0     0     0     0     0



C3 =                                

     0     0     0     0     0
     0     0     0     0     0
     1     1     0     0     0
     1     1     0     0     0
     0     0     0     0     0

... и накрая C16 е равно на:

C16 =                                

     0     0     0     0     0
     0     0     0     0     0
     0     0     0     0     0
     0     0     0     1     1
     0     0     0     1     1

Както можете да видите, това е като по-малка матрица (B) при движение вътре в по-голямата (A).

Много благодаря,


person Iman    schedule 16.07.2015    source източник
comment
какъв точно е въпросът ти тук?   -  person shrey    schedule 16.07.2015
comment
@shrey Как да преместите матрица A вътре в матрица B.   -  person Iman    schedule 18.07.2015


Отговори (3)


Можете да постигнете това, което искате, като използвате circshift(...) в съответните редове и колони, за да изместите стойностите около матрицата. Примерът, който споменавате, е примерът, показан в частта „Преместване на елементи на матрица“ на страницата с матрица 4x4.

Вземете например

A = [1 1 0 0; 1 1 0 0; 0 0 0 0; 0 0 0 0]
A =

     1     1     0     0
     1     1     0     0
     0     0     0     0
     0     0     0     0
Y = circshift(A,[1 1])
Y =

     0     0     0     0
     0     1     1     0
     0     1     1     0
     0     0     0     0

От уебсайта на Mathworks има вградена функция, която изглежда, че ще направи точно това, което искате. Точният код за показване на 16-те комбинации на матрица 5x5, които поддържат илюзията за малка матрица, движеща се през голяма, би бил

РЕДАКТИРАНО: така че сега има матрица 5x5x16 с изходи, наречени C

A=zeros(5,5);
A(1:2,1:2)=1
c=1;C=zeros(5,5,16);
for i=0:3
    for j=0:3
        C(:,:,c)=circshift(A,[i j])
        c=c+1;
    end
end

Което дава изхода (ЗАБЕЛЕЖКА, че изходът не е редактиран)

A =

     1     1     0     0     0
     1     1     0     0     0
     0     0     0     0     0
     0     0     0     0     0
     0     0     0     0     0


ans =

     1     1     0     0     0
     1     1     0     0     0
     0     0     0     0     0
     0     0     0     0     0
     0     0     0     0     0


ans =

     0     1     1     0     0
     0     1     1     0     0
     0     0     0     0     0
     0     0     0     0     0
     0     0     0     0     0


ans =

     0     0     1     1     0
     0     0     1     1     0
     0     0     0     0     0
     0     0     0     0     0
     0     0     0     0     0


ans =

     0     0     0     1     1
     0     0     0     1     1
     0     0     0     0     0
     0     0     0     0     0
     0     0     0     0     0


ans =

     0     0     0     0     0
     1     1     0     0     0
     1     1     0     0     0
     0     0     0     0     0
     0     0     0     0     0


ans =

     0     0     0     0     0
     0     1     1     0     0
     0     1     1     0     0
     0     0     0     0     0
     0     0     0     0     0


ans =

     0     0     0     0     0
     0     0     1     1     0
     0     0     1     1     0
     0     0     0     0     0
     0     0     0     0     0


ans =

     0     0     0     0     0
     0     0     0     1     1
     0     0     0     1     1
     0     0     0     0     0
     0     0     0     0     0


ans =

     0     0     0     0     0
     0     0     0     0     0
     1     1     0     0     0
     1     1     0     0     0
     0     0     0     0     0


ans =

     0     0     0     0     0
     0     0     0     0     0
     0     1     1     0     0
     0     1     1     0     0
     0     0     0     0     0


ans =

     0     0     0     0     0
     0     0     0     0     0
     0     0     1     1     0
     0     0     1     1     0
     0     0     0     0     0


ans =

     0     0     0     0     0
     0     0     0     0     0
     0     0     0     1     1
     0     0     0     1     1
     0     0     0     0     0


ans =

     0     0     0     0     0
     0     0     0     0     0
     0     0     0     0     0
     1     1     0     0     0
     1     1     0     0     0


ans =

     0     0     0     0     0
     0     0     0     0     0
     0     0     0     0     0
     0     1     1     0     0
     0     1     1     0     0


ans =

     0     0     0     0     0
     0     0     0     0     0
     0     0     0     0     0
     0     0     1     1     0
     0     0     1     1     0


ans =

     0     0     0     0     0
     0     0     0     0     0
     0     0     0     0     0
     0     0     0     1     1
     0     0     0     1     1
person Matt    schedule 16.07.2015
comment
Тъй като Matlab има вградена функция, която решава проблема. Ако погледнете внимателно въпроса, той просто посочва, че изглежда, че матрицата 2x2 се движи през по-голямата матрица 5x5, а не че действителното движение на по-малката матрица през по-голямата е от съществено значение за решението на проблема. - person Matt; 16.07.2015
comment
OP иска изход от 16 матрици (в примера). Моят код извежда това и не мисля, че има значение, ако и двамата трябва да използваме for цикли, независимо дали използвате индексиране или circshift. - person user1543042; 16.07.2015
comment
Използването на вградени функции на matlab обикновено има по-добра производителност от персонализираните функции, които правят същото, и смятам, че използването на клетъчен масив в този случай е ненужно. Ако редактирате публикацията си, ще се отърва от отрицателния вот, за да може да се върне към неутрален. - person Matt; 16.07.2015
comment
Съгласен съм, че използването на circshift е по-добър отговор, но мисля, че тъй като не знаем какво иска OP с тези матрици, клетъчният масив е по-добрият вариант. - person user1543042; 16.07.2015
comment
Ще призная, че първоначално малко прибързах с гласуването си против. Правите някои валидни точки и най-доброто решение вероятно е комбинация от двата отговора и известно разяснение на въпроса. Вярвам, че има circshift метод, който може да се обобщи за матрици с произволни размери, така че да може да върне всички непрекъснати комбинации от по-малка матрица вътре в по-голяма матрица; поне за разредени матрици, където повечето от елементите са 0. - person Matt; 16.07.2015

Един векторизиран подход с bsxfun -

%// Get sizes and form size parameters for creating output
[mA,nA] = size(A);
[mB,nB] = size(B);
mC = mA - mB + 1;
nC = nA - nB + 1;

%// Get linear indices
stage1 = bsxfun(@plus,[1:mB]',[0:nB-1]*mA);    %//'
stage2 = bsxfun(@plus,[1:mC]',[0:nC-1]*mA)-1;  %//'
idx = bsxfun(@plus,stage1(:),stage2(:).' + [0:mC*nC-1]*mA*nA);   %//'

%// Replicate A to setup output; index into it with idx & replace B
C = repmat(A,1,1,mC*nC);
C(idx) = repmat(B(:),1,mC*nC)

Примерно изпълнение -

A =
     1     1     8     4
     9     8     8     2
     7     9     5     1
     7     9     2     9
B =
     3     5
     3     6
     3     1
C(:,:,1) =
     3     5     8     4
     3     6     8     2
     3     1     5     1
     7     9     2     9
C(:,:,2) =
     1     1     8     4
     3     5     8     2
     3     6     5     1
     3     1     2     9
C(:,:,3) =
     1     3     5     4
     9     3     6     2
     7     3     1     1
     7     9     2     9
....

C(:,:,6) =
     1     1     8     4
     9     8     3     5
     7     9     3     6
     7     9     3     1
person Divakar    schedule 17.07.2015
comment
Благодаря за отделеното време. Вашето решение също изглежда страхотно! - person Iman; 18.07.2015

Мисля, че това е добър начин да се направи нещо подобно

A = zeros(5);
B = ones(2);
C = cell(size(A,1)-size(B,1) + 1, size(A,2)-size(B,2) + 1);

for i = 1:size(A,1)-size(B,1) + 1
    for j = 1:size(A,2)-size(B,2) + 1
        C{i, j} = A;
        C{i, j}(i:i+size(B,1) - 1, j:j+size(B,2) - 1) = B;

        % Additional code here
    end
end

C = C(:);

% Additional code here
person user1543042    schedule 16.07.2015
comment
Благодаря за отделеното време приятелю. Изглежда страхотно, също! - person Iman; 18.07.2015