Прежде всего, если изображение не делится равномерно на S
, вы получаете ошибку.Вам нужно добавить floor
здесь:
sizeRowsOut = floor((rowsIn-F)/S) + 1;
sizeColsOut = floor((colsIn-F)/S) + 1;
Основной двойной цикл можно немного упростить.Вместо зацикливания входного изображения с шагом S
и вычисления местоположения в выходном изображении путем деления на S
, зацикливание выходного изображения, а затем вычисление местоположения во входном изображении:
for r=1:sizeRowsOut
r_in = (r-1)*S; % NOTE! the actual location is r_in+1
for c=1:sizeColsOut
c_in = (c-1)*S;
sampleWindow = input(r_in+(1:F),c_in+(1:F));
% ...
outConvAcc(r,c,depthInput) = dotProdc;
end
end
(Обратите внимание, что все это индексирование выглядит немного опрятнее с индексацией на основе 0, но, увы.)
Здесь вам больше не нужен if
.input
гарантированно будет достаточно большим, чтобы соответствовать этому ядру, путем вычисления индексов.
Далее, вам нужно знать порядок данных в памяти и выполнять циклчто вы получаете доступ к данным в таком порядке.Это оптимизирует использование кэша.MATLAB равен основной столбец , что означает, что каждый столбец сохраняется последовательно.Ваш внутренний цикл проходит по ряду (по столбцам), что означает, что вы выполняете цикл в неправильном порядке.Просто поменяйте местами циклы r
и c
для хорошего увеличения скорости (заметно только для больших изображений):
for c=1:sizeColsOut
c_in = (c-1)*S;
for r=1:sizeRowsOut
r_in = (r-1)*S;
Наконец, бит внутри основного двойного цикла: это сложнее, чемэто должно быть из-за петли.В MATLAB вам это не нужно:
sampleWindow = input(r_in+(1:F),c_in+(1:F));
dotProd = sum(sampleWindow(:) .* kernelf(:));
или просто:
dotProd = dot(sampleWindow(:), kernelf(:));
или даже:
dotProd = sampleWindow(:).' * kernelf(:);
Но если вы хотите выписатьВнутренний цикл, также я рекомендую вам не копировать часть изображения, а напрямую обращаться к данным на изображении:
dotProd = 0;
for jj=1:F
for ii=1:F
dotProd = dotProd + input(r_in+ii,c_in+jj) * kernelf(ii,jj);
end
end
Это намного чище и удобочитаемее (IMO), потому что естьменьше переменных для отслеживания.
О, и еще одна проблема: цветные изображения.Если depthInput>1
, то вы читаете с первого канала и записываете на последний канал.Вы вообще не выполняете обработку цвета!
Поскольку измерение цвета сохраняется последним, наиболее эффективным способом является вызов этой свертки значения серого один раз для каждого цветового канала.