MATLAB векторизовать

Мне было интересно, может ли кто-нибудь помочь мне векторизовать этот фрагмент кода.

fr_bw — это матрица.

 for i=1:height
   for j=1:width      
                [min_w, min_w_index] = min(w(i,j,:));  
                mean(i,j,min_w_index) = double(fr_bw(i,j));
                sd(i,j,min_w_index) = sd_init;
     end
end

person user729206    schedule 04.05.2011    source источник
comment
Является ли fr_bw матрицей или функцией?   -  person    schedule 04.05.2011
comment
Извините, я хотел добавить это. Да, fr_bw — это матрица.   -  person user729206    schedule 04.05.2011
comment
Объясните, пожалуйста, тот, кто ответил на этот вопрос? Это резонный вопрос.   -  person Jason S    schedule 04.05.2011


Ответы (2)


Я не могу помочь вам с этим sif (match == 0) — если это должно быть if (match == 0), вы не меняете match, чтобы его можно было вывести за пределы цикла.

Иначе как насчет этого:

[min_w, min_w_index] = min(w, [], 3);
r = repmat((1:height)',1,width);
c = repmat(1:width,height,1);
ind = sub2ind(size(w),r(:),c(:),min_w_index(:));
w_mean(ind) = double(fr_bw);
w_sd(ind) = repmat(sd_init,height,width);

(Обратите внимание, что mean — это встроенная функция, поэтому я переименовал ваши переменные в w_mean и w_sd.)

Вызов sub2ind дает вам линейные индексы, соответствующие нижним индексам. (Прямые индексы не работают; z([a1 a2 a3],[b1 b2 b3],[c1 c2 c3]) относится к 27 элементам в массиве z с индексами, которые являются декартовым произведением указанных индексов, а не z(a1,b1,c1), z(a2,b2,c2) и z(a3,b3,c3), как можно было бы ожидать.)

Вот иллюстрация этой техники:

>> height = 6; width = 4;
>> w = randi(1000,height,width,2)

w(:,:,1) =

   426   599    69   719
   313   471   320   969
   162   696   531   532
   179   700   655   326
   423   639   408   106
    95    34   820   611


w(:,:,2) =

   779   441   638   696
   424   528   958    68
    91   458   241   255
   267   876   677   225
   154   519   290   668
   282   944   672   845

>> [min_w, min_w_index] = min(w, [], 3);
>> min_w_index

min_w_index =

     1     2     1     2
     1     1     1     2
     2     2     2     2
     1     1     1     2
     2     2     2     1
     1     1     2     1

>> z = zeros(height,width,2);
>> r = repmat((1:height)',1,width);
>> c = repmat(1:width,height,1);
>> ind = sub2ind(size(w),r(:),c(:),min_w_index(:));
>> z(ind) = 1

z(:,:,1) =

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


z(:,:,2) =

     0     1     0     1
     0     0     0     1
     1     1     1     1
     0     0     0     1
     1     1     1     0
     0     0     1     0
person Jason S    schedule 04.05.2011
comment
Я удалил оператор if. - person user729206; 04.05.2011
comment
@Richie Спасибо за ваш ответ, кажется, что он работает не так хорошо, как цикл for, я не знаю, почему, но код, похоже, обеспечивает лучшую производительность, но не дает правильных результатов, не могли бы вы увидеть причину? - person user729206; 05.05.2011
comment
без дополнительного контекста/информации о том, что вы ожидаете, мы не сможем диагностировать ваши проблемы. - person Jason S; 05.05.2011
comment
Кажется, что в w_mean остались значения, которых не должно быть после нескольких запусков кода. Итак, я имею в виду, что этот фрагмент кода запускается несколько раз и, похоже, не обновляется должным образом, кажется, что это происходит с использованием цикла for, это помогает, это трудно объяснить? - person user729206; 05.05.2011
comment
Если у вас нет примеров данных, которые я могу использовать, я не могу воспроизвести их со своей стороны. - person Jason S; 05.05.2011

Несколько комментариев к вашему коду:

  1. Вы имели в виду if, а не sif?

  2. В настоящее время код не воспроизводится, так как вы не предоставили примеры переменных w, fr_bw и sd_init. Это затрудняет точный ответ.

  3. Похоже, вы присваиваете значения переменной с именем mean. Это затенит функцию mean и, вероятно, вызовет у вас огорчение.

  4. Я только предполагаю, но я не думаю, что double делает то, что вы думаете. Вам не нужно преобразовывать отдельные элементы числовой матрицы в тип double; они уже правильного типа. (С другой стороны, если fr_bw имеет другой тип, скажем, целые числа, то вам следует создать новую переменную dbl_fr_bw = double(fr_bw); перед циклами.

Возможно, вам потребуется настроить измерение, по которому вы вычисляете минимумы, но первую строку цикла можно заменить на

[min_w, min_w_index] = min(w, [], 3)

Вторая строка с

mean_values(:, :, min_w_index) = double(fr_bw)

Не уверен насчет третьей строки, так как не знаю, что такое sd_init.

person Richie Cotton    schedule 04.05.2011
comment
Ваше второе предложение строки не сработает. Попробуй. Вы получите ошибку. - person Jason S; 04.05.2011
comment
а именно индексы индексов независимы и не работают с матрицей значений. Если все значения min_w_index не совпадают, это относится к индексам, которые представляют собой все строки и столбцы и объединение всех значений min_w_index. Это трехмерный срез средних_значений, и MATLAB ожидает, что правая часть будет трехмерной матрицей правильного размера. - person Jason S; 04.05.2011
comment
@Jason S: Хороший улов; оскорбительная строка удалена. Прислушаюсь к вашему ответу. - person Richie Cotton; 04.05.2011
comment
Я мог бы поклясться, что есть способ сделать то, что вы предлагаете (это был и мой первый подход, пока он не сработал), но, кроме логической адресации, я ничего не знаю. - person Jason S; 04.05.2011
comment
@Jason, @Richie Спасибо за ваш ответ, похоже, он работает не так хорошо, как цикл for, я не знаю, почему, но код, похоже, обеспечивает лучшую производительность, но не дает правильных результатов, не могли бы вы увидеть причину, почему ? - person user729206; 04.05.2011