前言
二維卷積的使用非常廣泛转锈,不論是出現(xiàn)處理還是深度學習都有涉及妇斤。但是目前網(wǎng)上大多羅列公式橙困,把其實簡單的二維卷積操作搞的很復雜。本文用在不使用任何的公式情況下乎串,明白二維卷積的使用方法,并能夠用Matlab編程實現(xiàn)速警。
二維卷積實現(xiàn)
二維卷積實現(xiàn)可以分為兩大步叹誉。一是預處理:將卷積核翻轉(zhuǎn)180°,將原始數(shù)據(jù)擴邊闷旧;二是滑動卷積計算长豁。下面按這兩個步驟分別說明:
預處理
如圖1所示即看的很明白。對卷積核翻轉(zhuǎn)180°就是"上下翻轉(zhuǎn)+左右翻轉(zhuǎn)"忙灼;對原始數(shù)據(jù)的擴邊其實就是為了"補0"好算匠襟,擴邊括多大呢?就看原始數(shù)據(jù)"左上角"那個點,卷積核是3x3宅此,那么左頂點一周也就要擴成3x3(卷積核中心和左頂點對齊后可以做"點乘")机错,也就是上爬范、下各括邊"fix(3/2) = 1"父腕。
圖1:二維卷積操作預處理
滑動卷積計算
滑動卷積計算,其實就是對應(yīng)的"兩個小矩陣"的"點乘并求和"青瀑。"滑動"是指:卷積核沿著"擴邊后的原始數(shù)據(jù)"從左到右璧亮,從上到下進行。如圖2所示:
圖2:滑動卷積計算
完成上面兩步斥难,二維卷積就做完了枝嘶!是不是很簡單?根本不需要看復雜的公式~
既然清楚了理論基礎(chǔ)哑诊,那就用Matlab實踐一下群扶。
clc; clear;
x = [-1 -2 -1;0 0 0;1 2 1]; % 卷積核——必須是方陣且為奇數(shù)行/列
data = [1 2 3 4 5;6 7 8 9 10;11 12 13 14 15;16 17 18 19 20;21 22 23 24 25]; % 原始數(shù)據(jù)
zidai = conv2(data,x,'same'); % matlab自帶的二維卷積函數(shù)
x = rot90(rot90(x)); % 新的卷積核
% 核的尺寸
size_x = size(x);
row_x = size_x(1); % 核的行數(shù)
col_x = size_x(2); % 核的列數(shù)
% 數(shù)據(jù)的尺寸
size_data = size(data);
row_data = size_data(1); % 數(shù)據(jù)的行數(shù)
col_data = size_data(2); % 數(shù)據(jù)的列數(shù)
% 核的中心元素:
centerx_row = round(row_x/2);
centerx_col = round(col_x/2);
centerx = x(centerx_row,centerx_col);
% 對原始數(shù)據(jù)擴邊:
data_tmp = zeros(row_data+row_x-1,col_data+row_x-1);
data_tmp(centerx_row:centerx_row+row_data-1,centerx_row:centerx_row+col_data-1) = data;
data_k = data_tmp;
% 擴邊后新數(shù)據(jù)矩陣尺寸:
size_data_k = size(data_k);
row_data_k = size_data_k(1);
col_data_k = size_data_k(2);
% m = centerx_row:row_data+row_x-2
% 開始卷積計算: m n 是新數(shù)據(jù)矩陣的正常索引
result = zeros(row_data_k,col_data_k);
% m n一般卷積步長都是1
for m = centerx_row:centerx_row+row_data-1
for n = centerx_row:centerx_row+col_data-1
% tt是臨時與卷積核大小相同的數(shù)據(jù)中的部分矩陣:
tt = data_k(m-(centerx_row-1):m+(centerx_row-1),n-(centerx_row-1):n+(centerx_row-1));
% juan是中間每一次卷積計算求和的中間量:
juan = sum(x.*tt);
result(m,n) = sum(juan(:));
end
end
% 求掉之前擴邊的0:
result = result(centerx_row:centerx_row+row_data-1,centerx_row:centerx_row+col_data-1)
說明:手動實現(xiàn)的matlab程序其實很簡單很好理解,可直接運行镀裤。