Есть ли причина, по которой вы не используете функцию свертки MATLAB, чтобы помочь вам в этом? Вы выполняете размытие с 3 x 3 усредняющим ядром с перекрывающимися окрестностями. Это именно то, что делает свертка. Вы можете выполнить это с помощью conv2
:
M2 = conv2(M, ones(3)/9, 'valid');
'valid'
флаг гарантирует, что вы возвращаете size(M) - 2
матрицу в обоих направлениях, как вы просили.
В вашем коде вы жестко закодировали это для матрицы 4 x 4. Для того, чтобы перепроверить, чтобы увидеть, если у нас есть правильные результаты, давайте генерировать случайные 4 х 4 матрица:
rng(123);
M = rand(4, 4);
s = size(M);
Если мы запустим это с вашим кодом, мы получаем:
>> M2
M2 =
0.5054 0.4707
0.5130 0.5276
Делать это с conv2
:
>> M2 = conv2(M, ones(3)/9, 'valid')
M2 =
0.5054 0.4707
0.5130 0.5276
Однако, если вы хотите сделать это из первых принципов, перекрывание пикселя ржать bourhoods очень трудно избежать с помощью петель. Два подхода for
, которые у вас есть, достаточно хороши, и он решает проблему соответствующим образом. Я бы сделал размер ввода вместо жесткого кодирования. Таким образом, написать функцию, которая делает что-то вроде этого:
function M2 = blur_fp(M)
s = size(M);
M2 = zeros(s(1) - 2, s(2) - 2);
for ii = 2 : s(1) - 1
for jj = 2 : s(2) - 1
p = M(ii - 1 : ii + 1, jj - 1 : jj + 1);
M2(ii - 1, jj - 1) = mean(p(:));
end
end
Первая строка кода определяет функцию, которую мы будем называть blur_fp
. Следующие пары строк кода определяют размер входной матрицы, а также инициализацию пустой матрицы для хранения выходных данных. Затем мы пробиваем каждое местоположение пикселя в матрице, которое возможно, если ядро не выходит за пределы границ изображения, мы захватываем 3 x 3 окрестности с каждым местоположением пикселя, выступающим в качестве центра, тогда мы получаем unroll матрица в один вектор столбца, найдите среднее значение и сохраните его в соответствующем выводе. Для небольших ядер и относительно больших матриц это должно выполняться нормально.
Для того, чтобы это немного дальше, вы можете использовать пользовательский Divakar «s im2col_sliding
функция, которая принимает пересекающиеся окрестности и разворачивает их в столбцы. Поэтому каждый столбец представляет собой окрестность, которая затем может размывать вход, используя умножение векторной матрицы.Вы бы затем использовать reshape
, чтобы изменить результат обратно в матрицу:
T = im2col_sliding(M, [3 3]);
V = ones(1, 9)/9;
s = size(M);
M2 = reshape(V * T, s(1) - 2, s(2) - 2);
К сожалению, это не может быть сделано в одной строке, если не использовать встроенные функции. Я не уверен, каково ваше намерение, но, надеюсь, диапазон подходов, которые вы здесь видели, дал вам некоторое представление о том, как это сделать эффективно. Кстати, использование петель для малых матриц (т. Е. 4 х 4) может быть лучше по эффективности. Вы начнете замечать изменения производительности при увеличении размера ввода ... опять же, я бы сказал, что использование циклов конкурентоспособно по сравнению с R2015b, когда JIT значительно улучшилось.
Спасибо! Я думаю, что намерение упражнения состояло в том, чтобы сделать это, используя только «первые принципы», и предполагается, что мы не знаем этих функций, о которых вы говорите. Но все и все, я думаю, это полезно для моего фактического знания о Matlab. –
@DylanBrown ОК, в этом случае то, что у вас есть с двумя циклами 'for', достаточно для первых принципов. Вам нужна дополнительная помощь? Если нет, тогда мне бы это понравилось, если бы вы могли принять мой ответ. Это позволит сообществу понять, что вам больше не нужна помощь. Удачи! – rayryeng
@DylanBrown Я также отредактирую свое сообщение, чтобы использовать два цикла 'for' без жесткого кодирования размера ввода. Я сделаю его динамичным. – rayryeng