Caffe中卷積運算的原理與實現

2021-08-01 01:33:06 字數 1500 閱讀 5322

caffe中卷積運算設計的很巧妙,今天就來討論一下caffe中卷積運算的原理,最後會給出乙個自己的實現版本,便於初學者理解。

俗話說,一圖勝千言,首先先給出原理示意圖,為了方便理解,這裡以二維核為例

滑動視窗在影象中每滑動乙個地方,將影象中該滑動視窗影象展開為一列,所有列組成圖中的滑動視窗矩陣,這裡假設pad=1,stride=1,k=3,則滑動視窗矩陣每行大小為w*h,一共k*k行.

每個核展開為一行,n個核形成的核矩陣大小為n*k*k。

最後將核矩陣和滑動視窗矩陣相乘,每一行就是乙個特徵圖,n個卷積核形成n個特徵圖。

擴充套件到三維核

三維核就是多了乙個通道的概念,原理與二維核一樣。

caffe原始碼中的src\caffe\util\im2col.cpp中的im2col_cpu函式給出了實現,但是個人覺得並不利於初學者的理解,這裡給出乙個自己根據該原理實現的**,這裡只考慮二維核的情況

#define  saturate(x)   (uchar)(((x) & ~255) == 0 ? (x) : ~((x)>>31))

void convolution1(const mat &srcimage, const mat &kernel, mat &dstimage)}}

// 卷積核與滑動視窗矩陣相乘,這部分可以使用矩陣運算加速(比如blas,eigen)

float *dataofkernel = (float *)kernel.data;

uchar *dataofdst = dstimage.data;

for (int x = 0; x <= slidingwindowmat.cols - 1; ++x)

// 卷積結果賦值為結果影象,注意溢位的處理!

dataofdst[x] = saturate((int)sum);

}} // convolution1

下面是測試**

void testconvolution1()

原圖

結果圖

由於示例程式中的卷積核是垂直方向的sobel運算元,所以結果影象中對垂直方向的邊緣比較敏感,而對水平方向的邊緣不敏感。

2017-5-13 17:04:46

Caffe的卷積原理

caffe中的卷積計算是將卷積核矩陣和輸入影象矩陣變換為兩個大的矩陣a與b,然後a與b進行矩陣相乘得到結果c 利用gpu進行矩陣相乘的高效性 三個矩陣的說明如下 1 在矩陣a中 m為卷積核個數,k k k,等於卷積核大小,即第乙個矩陣每行為乙個卷積核向量 是將二維的卷積核轉化為一維 總共有m行,表示...

caffe中的卷積

如上,將三維的操作轉換到二維上面去做,然後呼叫gemm庫進行矩陣間的運算得到最後結果。兩個矩陣相乘,需要中間的那個維度相同,這個相同的維度就是c k k,其中c是feature map的維度,k為卷積核的邊長。按照卷積核在feature map上面滑窗的順序將其展開成二維的。在三維上面看,就是卷積核...

Caffe中卷積層的實現

出處 將尺寸為k k的卷積核在某個位置對應的feature map區域表示為k k的一維向量 將feature map各個通道對應的向量之間,串聯起來 那麼尺寸k k的卷積核在某個位置對應的各個通道的feature map,組合起來就是長度為c k k的一維向量。當卷積核對應到新的位置上,又得到新的...