Как эффективно создать нелинейную маску с использованием двух граничных массивов - PullRequest
0 голосов
/ 05 июня 2019

Я могу создать нелинейную маску на основе двух массивов, содержащих нижнюю и верхнюю границу маски. Все значения между ними должны быть установлены в 1. Способ, которым я сейчас занимаюсь, кажется, занимает довольно много времени, и это становится узким местом. Мне было интересно, есть ли способ сделать это более эффективным по времени.

Во-первых, я думал решить эту проблему, используя парфоры для увеличения скорости. Но так как это один из внутренних циклов в моем коде, они кажутся крайне неэффективными, поскольку более целесообразно использовать parfor во внешнем цикле, учитывая накладные расходы по расписанию. Таким образом, параллельные методы не вариант.

Смотрите здесь создание маски:

mask = zeros(size(im));
n = length(bufLow);

for i=1:1:n                 
   mask(bufLow(i):bufHigh(i),i) = 1;
end    

im - это матрица определенного размера, а bufLow и bufHigh - это массивы размером, равным горизонтальному размеру im описывая верхнюю и нижнюю границы для каждого столбца im . Между этими значениями все должно быть установлено на 1.

Таким образом, цель состоит в том, чтобы иметь что-то, что максимально сокращает время выполнения этого цикла. Мне было интересно, есть ли кто-то со знанием, чтобы просветить меня.

Bests

Matthijs

1 Ответ

1 голос
/ 06 июня 2019

Я признаю, что ваш вопрос допускает некоторую интерпретацию и догадки, но из предоставленного вами кода у меня есть идея, чего вы хотите достичь: для i -ого столбца в вашем mask вы хотитеустановить все пиксели между начальным индексом (который будет bufLow(i)) и конечным индексом (bufHigh(i)) равным 1. Это правильно?

Итак, моя идея "векторизовать" ваш цикл будет заключаться впереведите индексы «на столбец» индекса (или массива) в вашем bufxxx в «изображение» линейные индексы , а затем найдите все линейные индексы между начальным и конечным индексами.Последняя является (общей) проблемой, которая уже имеет несколько важных ответов, например этот от Divakar .

Я включил его ответ в свое решение.Пожалуйста, смотрите следующий код:

dim = 25;

bufLow = int32(10 * rand(1, dim) + 1);
bufHigh = int32(10 * rand(1, dim) + 15);

% Reference implementation from question
mask = zeros(dim);
n = length(bufLow);
for i=1:1:n                 
   mask(bufLow(i):bufHigh(i), i) = 1;
end  

% Show mask
figure(1);
imshow(mask);

% Implementation using Divakar's approach

% Translate subscript indices to linear indices
bufLow = bufLow + (dim .* (0:dim-1));
bufHigh = bufHigh + (dim .* (0:dim-1));

% Divakar's approach for finding all indices between two boundaries
lens = bufHigh - bufLow + 1;
shift_idx = cumsum(lens(1:end-1)) + 1;
id_arr = ones(1, sum(lens));
id_arr([1 shift_idx]) = [bufLow(1) bufLow(2:end) - bufHigh(1:end-1)];
out = cumsum(id_arr);

% Generating mask
mask2 = zeros(dim);
mask2(out) = 1;

% Show mask
figure(2);
imshow(mask2);

Полученные маски идентичны и выглядят следующим образом:

Mask

Чтобы иметьПосмотрите на производительность, я настроил отдельный сценарий синхронизации, используя оба подхода для увеличения измерения dim с 25 до 2500 с шагом 25. Результат выглядит следующим образом:

Comparison

Надеюсь, это поможет!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...