2010-04-26 4 views
4

У меня есть большая матрица, из которой я хотел бы собрать коллекцию подматриц. Если моя матрица равна NxN, а размер подматрицы - MxM, я хочу собрать подматрицы I=(N - M + 1)^2. Другими словами, мне нужна одна подматрица MxM для каждого элемента исходной матрицы, которая может находиться в верхнем левом углу такой матрицы.Октава: Несколько подматриц из матрицы

Вот код, у меня есть:

for y = 1:I 
    for x = 1:I 
     index = (y - 1) * I + x; 
     block_set(index) = big_mat(x:x+M-1, y:y+M-1) 
    endfor 
endfor 

выход, если а) не прав, и б) подразумевающее есть что-то в выражении big_mat(x:x+M-1, y:y+M-1), что может заставить меня, что я хочу, не нуждаясь в два для петель. Любая помощь была бы очень благодарна

+2

Кажется, что вы делаете это в Octave, но, возможно, этот вопрос MATLAB поможет вам дать некоторые идеи: http://stackoverflow.com/questions/2678857/general-method-for-making-sub-arrays- вокруг-а-особенно-элемент. – gnovice

ответ

5

В коде есть несколько неправильных вещей. Вот как я это сделать, если бы я использовать двойной цикл:

M = someNumber; 
N = size(big_mat,1); %# I assume big_mat is square here 

%# you need different variables for maxCornerCoord and nSubMatrices (your I) 
%# otherwise, you are going to index outside the image in the loops! 
maxCornerCoord = N-M+1; 
nSubMatrices = maxCornerCoord^2; 

%# if you want a vector of submatrices, you have to use a cell array... 
block_set = cell(nSubMatrices,1); 
%# ...or a M-by-M-by-nSubMatrices array... 
block_set = zeros(M,M,nSubMatrices); 
%# ...or a nSubMatrices-by-M^2 array 
block_set = zeros(nSubMatrices,M^2); 

for y = 1:maxCornerCoord 
    for x = 1:maxCornerCoord 
     index = (y - 1) * maxCornerCoord + x; 
     %# use this line if block_set is a cell array 
     block_set{index} = big_mat(x:x+M-1, y:y+M-1); 
     %# use this line if block_set is a M-by-M-by-nSubMatrices array 
     block_set(:,:,index) = big_mat(x:x+M-1, y:y+M-1); 
     %# use this line if block_set is a nSubMatrices-by-M^2 array 
     block_set(index,:) = reshape(big_mat(x:x+M-1, y:y+M-1),1,M^2); 
    endfor 
endfor 

EDIT

Я только что видел, что есть реализация im2col для Октава. Таким образом, вы можете переписать двойную петлю как

%# block_set is a M^2-by-nSubMatrices array 
block_set = im2col(big_mat,[M,M],'sliding'); 

%# if you want, you can reshape the result to a M-by-M-by-nSubMatrices array 
block_set = reshape(block_set,M,M,[]); 

Это, вероятно, быстрее, и экономит много цифровых деревьев.

+0

Thanks; есть ли способ сделать это без двойной петли? Я предполагаю, что производительность таких будет намного лучше, чем зацикленная версия ... – fbrereto

+0

@fbereto: Оказывается, вы можете написать это как 1-лайнер. См. Мое редактирование. – Jonas

+0

@ Джонас: о, похоже, вы уже думали о IM2COL, я думаю, что я не видел вашего редактирования ... Подумайте о добавлении перестановки/изменения, чтобы превратить его в нужную форму: 'block_set = reshape (permute (im2col (big_mat, [MM] , «скользящий»), [1 3 2]), 2,2, []); ' – Amro

0

О вашем выходе, являющемся неправильным, возможно, это связано с назначением. Вы пытаетесь присвоить матрицу векторную позицию. Попробуйте использовать

block_set(:,:,index) = big_mat(x:x+M-1, y:y+M-1) 

вместо этого.

+0

@ Офри: спасибо за наконечник. Что делать, если мне нужен вектор матриц? – fbrereto

+0

Технически, это то, что вы получите с помощью этого кода. его вектор матриц, но индекс для перехода к разным матрицам является третьим индексом. 1-й и 2-й индексы являются индексами внутри матрицы. Другая возможность - использовать массивы ячеек, но я думаю, что в этом случае 3D-матрица будет лучше. –

1

С помощью Mathematica: Этот код представляет собой матрицу, в которой каждый элемент является матрицей MxM с каждым элементом в исходной матрице в верхнем левом углу такой матрицы.

Матричные элементы справа и внизу дополняются х.

Partition[big_mat, {M, M}, {1, 1}, {1, 1}, x] 

Пример: alt text http://img130.imageshack.us/img130/6203/partitionf.png

Если оставить от й аргумента, то тогда он автоматически образцы периодически.