2012-09-06 2 views
2

У меня есть матрица сказатьИзменение нескольких элементов (известных координат) из матрицы без для цикла

Z = [1 2 3; 
    4 5 6; 
    7 8 9] 

Я должен изменить свои значения, скажем, в позиции (2,2) и (3,1) до некоторого заданного значения. У меня есть две матрицы rowNos и colNos, которые содержат эти позиции:

rowNos = [2, 3] 
colNos = [2, 1] 

Скажем, я хочу, чтобы изменить значение элементов в этих положениях 0.

Как я могу это сделать без использования для цикла?

+0

Почему вы хотите избежать цикла здесь? –

+2

@MarcusRiemer, потому что я собираюсь применить эту вещь на больших изображениях. На самом деле огромные. И я чувствую, Vectorization поможет моему коду работать намного быстрее, чем простой для циклов. – shahensha

ответ

5

Использование sub2ind, он будет конвертировать подиндексы линейных индексов, что ряд указывая на одно точное пятно в матрице (more info).

Z = [ 1 2 3 ; 4 5 6 ; 7 8 9]; 
rowNos = [2, 3]; 
colNos = [2, 1]; 

lin_idcs = sub2ind(size(Z), rowNos, colNos) 

Если вы хотите работать на все элементы на определенную строку и столбце (элементы в более высоких измерениях, что есть), вы также можете обратиться к ним с использованием линейной индексации. Это становится только немного сложнее вычисления их:

Z = reshape(1:4*4*3,[4 4 3]); 
rowNos = [2, 3]; 
colNos = [2, 1]; 

siz = size(Z); 
lin_idcs = sub2ind(siz, rowNos, colNos,ones(size(rowNos))); % just the first element of the remaining dimensions 
lin_idcs_all = bsxfun(@plus,lin_idcs',prod(siz(1:2))*(0:prod(siz(3:end))-1)); % all of them 
lin_idcs_all = lin_idcs_all(:); 

Z(lin_idcs_all) = 0; 

эксперимент немного с sub2ind, и пройти через мой код шаг за шагом, чтобы понять это.

Это было бы проще, если бы это был первый размер вы хотите, чтобы принять все элементы прочь, то вы могли бы использовать оператор двоеточия :

Z = reshape(1:3*4*4,[3 4 4]); 
rowNos = [2, 3]; 
colNos = [2, 1]; 

siz = size(Z); 
lin_idcs = sub2ind(siz(2:end),rowNos,colNos); 
Z(:,lin_idcs) = 0; 
+0

Большое спасибо @Gunther Struyf. Еще один маленький вопрос. Как расширить его до трехмерной матрицы? Что, если бы Z говорила матрицу 3x3x3. (Я действительно хочу изменить значения RGB изображения, поэтому я упростил его таким образом) Итак, как есть 3 значения, связанные с каждой позицией, и я хочу изменить их все с тремя другими заданными значениями. Как мне это сделать? – shahensha

+0

@Shahensha see edit ^^ (вы должны добавить это замечание в свой исходный вопрос в первую очередь imho) –

+0

Большое спасибо @Gunter Struyf – shahensha

2

Использование sub2ind с несколькими записями для строк и столбцов

Z(sub2ind(size(Z), rowNos, colNos))=0 

Пример:

Z = [1 2 3; 
    4 5 6; 
    7 8 9]; 

rowNos = [2, 3]; 
colNos = [2, 1]; 

Z(sub2ind(size(Z), rowNos, colNos))=0 

Z = 

    1  2  3 
    4  0  6 
    0  8  9 
+0

Большое спасибо @gevang. Ещё один маленький вопрос. Как расширить его до трехмерной матрицы? Что, если бы Z говорила матрицу 3x3x3. (Я действительно хочу изменить значения RGB изображения, поэтому я упростил его таким образом) Итак, как есть 3 значения, связанные с каждой позицией, и я хочу изменить их все на 3 других указанных значения. Как мне это сделать? – shahensha

+0

по тем же линиям с @Gunther Struyf, я бы также предложил для 3-мерных матриц (т. Е. RGB-изображений), зацикливающих на 3-м измерении, который является чистым и не дорогостоящим (даже для огромных 2-мерных измерений), т.е.'c = [-1; -2; -3]; для i = 1: 3, Z (sub2ind (размер (Z), rowNos, colNos, repmat (i, 1, size (rowNos, 2)))) = c (i); end' – gevang

1

Вы хотели бы сделать это

z(rowNos, colNos) 

, но вы не можете - MATLAB делает декартово произведение индексов. Вы можете сделать этот трюк

idx=(colNos-1)*size(z, 1)+rowNos; 
z(idx)=0 

Свести Z-матрицу и получить доступ к нему через линейный индекс, который представляет собой сочетание rowNos и colNos. Помните, что MATLAB выравнивает матрицу по столбцам (хранилище матриц на основе столбцов).

+1

, что по сути является тем, что делает 'sub2ind', но это работает только для 2d-матриц (трюк здесь, конечно, но для непрерывности проще просто использовать sub2ind) –

+0

Для более высоких измерений вы можете сделать тот же трюк, который на самом деле не трюк, а именно то, что делает sub2ind. Но это правда, что для этого требуется знание структуры данных MATLAB. sub2ind освобождает вас от этого, но мне нравится точно знать, как все работает. – angainor

+0

(nofi), поэтому вы также вычисляете среднее значение вектора, используя 'sum (x)/length (x)': p –

 Смежные вопросы

  • Нет связанных вопросов^_^