一些算子及不同類型的卷積


1、什么是算子及不同算子的介紹

  算子是一個函數空間到函數空間上的映射O:X→X。廣義上的算子可以推廣到任何空間,如內積空間等。

  在圖像處理中,通常會使用一些不同的算子來對圖像進行處理。下面介紹一下圖像處理中常用的一些算子。

1.相關算子(Correlation Operator)

  相關算子的表達方法是

\[{\rm{g}} = f \otimes h\]

  其具體公式為

\[g(i,j) = \sum\limits_{k,l} {f(i + k,j + l)h(k,l)} \]

運算步驟為:

1)滑動核,使其中心位於輸入圖像g的(i,j)像素上

2)利用上式求和,得到輸出圖像的(i,j)像素值

3)充分上面操縱,直到求出輸出圖像的所有像素值

例:

  假設

\[{\rm{a}} = \left( {\begin{array}{*{20}{c}}
{17}&{24}&1&{\begin{array}{*{20}{c}}
8&{15}
\end{array}}\\
{23}&5&7&{\begin{array}{*{20}{c}}
{14}&{16}
\end{array}}\\
4&6&{13}&{\begin{array}{*{20}{c}}
{20}&{22}
\end{array}}\\
{\begin{array}{*{20}{c}}
{10}\\
{11}
\end{array}}&{\begin{array}{*{20}{c}}
{12}\\
{18}
\end{array}}&{\begin{array}{*{20}{c}}
{19}\\
{25}
\end{array}}&{\begin{array}{*{20}{c}}
{\begin{array}{*{20}{c}}
{21}\\
2
\end{array}}&{\begin{array}{*{20}{c}}
3\\
9
\end{array}}
\end{array}}
\end{array}} \right)h = \left( {\begin{array}{*{20}{c}}
8&1&6\\
3&5&7\\
4&9&2
\end{array}} \right)\]

 

image

Matlab 函數:imfilter(A,h)

 那么計算輸出圖像的(2,4)元素=image

 

2.卷積算子(Convolution)

  卷積算子的表達方法是

\[g = f*h\]

  其具體公式為

\[g(i,j) = \sum\limits_{k,l} {f(i - k,j - l)h(k,l) = } \sum\limits_{k,l} {f(k,l)h(i - k,j - l)} \]

運算步驟為:

1)將核圍繞中心旋轉180度

2)滑動核,使其中心位於輸入圖像g的(i,j)像素上

3)利用上式求和,得到輸出圖像的(i,j)像素值

4)充分上面操縱,直到求出輸出圖像的所有像素值

    將上例中的數據做卷積算子運算為:

imageMatlab 函數:Matlab 函數:imfilter(A,h,'conv')% imfilter默認是相關算子,因此當進行卷積計算時需要傳入參數'conv'

  那么計算輸出圖像的(2,4)元素=image

 

3.邊緣效應

當對圖像邊緣的進行濾波時,核的一部分會位於圖像邊緣外面。

常用的策略包括:

1)使用常數填充:imfilter默認用0填充,這會造成處理后的圖像邊緣是黑色的。

 

2)復制邊緣像素:I3 = imfilter(I,h,'replicate');

image

4.常用濾波

fspecial函數可以生成幾種定義好的濾波器的相關算子的核。

例:unsharp masking 濾波

1
2
3
4
5
I = imread( 'moon.tif' );
h = fspecial( 'unsharp' );
I2 = imfilter(I,h);
imshow(I), title( 'Original Image' )
figure, imshow(I2), title( 'Filtered Image' )

 

 

5、在圖像處理中卷積的計算(注意,下面藍色矩陣周圍有一圈灰色的框,那些就是上面所說到邊緣效應)


這里的藍色矩陣就是輸入的圖像,粉色矩陣就是卷積層的神經元,這里表示了有兩個神經元(w0,w1)。綠色矩陣就是經過卷積運算后的輸出矩陣,這里的步長設置為2。

 

藍色的矩陣(輸入圖像)對粉色的矩陣(filter)進行矩陣內積計算並將三個內積運算的結果與偏置值b相加(比如上面圖的計算:2+(-2+1-2)+(1-2-2) + 1= 2 - 3 - 3 + 1 = -3),計算后的值就是綠框矩陣的一個元素。

 

下面的動態圖形象地展示了卷積層的計算過程:

 

 

6、在圖像處理中常用到的卷積核

   了解了卷積在圖像處理中的應用形式核方法后,下面是一些在圖像處理中常用到的模板(卷積核)


 

7、sobel在圖像處理進行邊沿檢測

  邊緣檢測常常借助於空域微分算子進行,通過將其模板與圖像卷積完成.主要有一次微分(Sobel算子、Robert算子)、二次微分(Laplacian算子)等。在梯度法的基礎上,Sobel提出了一種強方向差分運算與局部平均相結合的方法,即Sobel算子.

 

  sobel算子的思想,Sobel算子認為,鄰域的像素對當前像素產生的影響不是等價的,所以距離不同的像素具有不同的權值,對算子結果產生的影響也不同。一般來說,距離越遠,產生的影響越小。其基本思想是,以待增強圖像的任意像素(i,j)為中心,截取一個3*3像素的窗口,如下式所示:

\[\begin{array}{*{20}{c}}
{{\rm{f}}(i - 1,j - 1)}&{{\rm{f}}(i - 1,j)}&{{\rm{f}}(i - 1,j + 1)}\\
{{\rm{f}}(i,j - 1)}&{{\rm{f}}(i,j)}&{{\rm{f}}(i,j + 1)}\\
{{\rm{f}}(i + 1,j + 1)}&{{\rm{f}}(i + 1,j)}&{{\rm{f}}(i + 1,j + 1)}
\end{array}\]

   分別計算中心像素在x,y方向上的梯度

    

 

 

  sobel算子的原理,對傳進來的圖像像素做卷積,卷積的實質是在求梯度值,或者說給了一個加權平均,其中權值就是所謂的卷積核;然后對生成的新像素灰度值做閾值運算,以此來確定邊緣信息。

Gx是對原圖x方向上的卷積,Gy是對原圖y方向上的卷積;

原圖中的作用點像素值通過卷積之后為:

可以簡化成:

比如,一下矩陣為原圖中的像素點矩陣,帶入上式中的A,最終得到的G或者|G|是下面(x,y)處的像素值,可以自己去搜索下卷積的含義來理解。

 

另外,卷積核也可以旋轉,用與查找不與x,y軸平行或垂直的方向上的邊緣。

 

得到像素點新的像素值之后,給定一個閾值就可以得到sobel算子計算出的圖像邊緣了。

通常,為了消除噪聲對sobel算子的影響,會增加一個預處理的操作,主要是做平滑處理降低噪聲的影響。

 

下面是其MATLAB的實現及效果圖

f=imread('1.jpg');
f=rgb2gray(f);%轉化成灰度圖
f=im2double(f);%函數im2double 將其值歸一化到0~1之間
%使用垂直Sobcl箅子.自動選擇閾值
[VSFAT Threshold]=edge(f, 'sobel','vertical'); %邊緣探測
figure,imshow(f),title(' 原始圖像,');%顯示原始圖像
figure,imshow(VSFAT),title( '垂直圖像邊緣檢測');
%顯示邊緣探測圖像
%使用水平和垂直Sobel算子,自動選擇閾值
SFST=edge(f,'sobel',Threshold);
figure,imshow(SFST),title('水平和垂直圖像邊緣檢測');
%顯示邊緣探測圖像
%使用指定45度角Sobel算子濾波器,指定閡值
s45=[-2 -1 0;-1 0 1;0 1 2];
SFST45=imfilter(f,s45,'replicate');%功能:對任意類型數組或多維圖像進行濾波。
SFST45=SFST45>=Threshold;
figure,imshow(SFST45),title('45度角圖像邊緣檢測') ;
%顯示邊緣探測圖像

  

相關的C++代碼實現為:

#include "core/core.hpp"   
#include "highgui/highgui.hpp"   
#include "imgproc/imgproc.hpp"   
#include "iostream" 
 
using namespace std;
using namespace cv;
 
int main(int argc, char *argv[])
{
    Mat image = imread("qiaoba.jpg", 0);
    Mat imageX = Mat::zeros(image.size(), CV_16SC1);
    Mat imageY = Mat::zeros(image.size(), CV_16SC1);
    Mat imageXY = Mat::zeros(image.size(), CV_16SC1);
    Mat imageX8UC;
    Mat imageY8UC;
    Mat imageXY8UC;
    if (!image.data)
    {
        return -1;
    }
    GaussianBlur(image, image, Size(3, 3), 0); //高斯濾波消除噪點 
    uchar *P = image.data;
    uchar *PX = imageX.data;
    uchar *PY = imageY.data;
    int step = image.step;
    int stepXY = imageX.step;
    for (int i = 1; i<image.rows - 1; i++)
    {
        for (int j = 1; j<image.cols - 1; j++)
        {
            //通過指針遍歷圖像上每一個像素 
            PX[i*imageX.step + j*(stepXY / step)] = abs(P[(i - 1)*step + j + 1] + P[i*step + j + 1] * 2 + P[(i + 1)*step + j + 1] - P[(i - 1)*step + j - 1] - P[i*step + j - 1] * 2 - P[(i + 1)*step + j - 1]);
            PY[i*imageX.step + j*(stepXY / step)] = abs(P[(i + 1)*step + j - 1] + P[(i + 1)*step + j] * 2 + P[(i + 1)*step + j + 1] - P[(i - 1)*step + j - 1] - P[(i - 1)*step + j] * 2 - P[(i - 1)*step + j + 1]);
        }
    }
    addWeighted(imageX, 0.5, imageY, 0.5, 0, imageXY);//融合X、Y方向   
    convertScaleAbs(imageX, imageX8UC);
    convertScaleAbs(imageY, imageY8UC);
    convertScaleAbs(imageXY, imageXY8UC);   //轉換為8bit圖像 
 
    Mat imageSobel;
    Sobel(image, imageSobel, CV_8UC1, 1, 1); //Opencv的Sobel函數 
 
    imshow("Source Image", image);
    imshow("X Direction", imageX8UC);
    imshow("Y Direction", imageY8UC);
    imshow("XY Direction", imageXY8UC);
    imshow("Opencv Soble", imageSobel);
    waitKey();
    return 0;
}

  

 

sobel的優缺點也比較明確。

優點:計算簡單,速度很快;

缺點:計算方向單一,對復雜紋理的情況顯得乏力;

  直接用閾值來判斷邊緣點欠合理解釋,會造成較多的噪聲點誤判。

 

 

 

 

 

 

2、對深度可分離卷積、分組卷積、擴張卷積、轉置卷積(反卷積)的理解

  前面講解了卷積的原理,及卷積在圖像中的基礎應用,但是在實際應用中,根據需求和硬件條件的不同,卷積的應用方法和名稱也不同。這里有必要將一些常用的卷積拿出來單獨講一下。不過在介紹前需要了解一些在深度學習中卷積的基本結構的定義:

卷積核大小(Kernel Size):定義了卷積操作的感受野。在二維卷積中,通常設置為3,即卷積核大小為3×3。

步幅(Stride):定義了卷積核遍歷圖像時的步幅大小。其默認值通常設置為1,也可將步幅設置為2后對圖像進行下采樣,這種方式與最大池化類似。

邊界擴充(Padding):定義了網絡層處理樣本邊界的方式。當卷積核大於1且不進行邊界擴充,輸出尺寸將相應縮小;當卷積核以標准方式進行邊界擴充,則輸出數據的空間尺寸將與輸入相等。

輸入與輸出通道(Channels):構建卷積層時需定義輸入通道I,並由此確定輸出通道O。這樣,可算出每個網絡層的參數量為I×O×K,其中K為卷積核的參數個數。例,某個網絡層有64個大小為3×3的卷積核,則對應K值為 3×3 =9。

1、深度可分離卷積

    在可分離卷積(separable convolution)中,通常將卷積操作拆分成多個步驟。而在神經網絡中通常使用的就是深度可分離卷積(depthwise separable convolution)。 

  假設有一個3×3大小的卷積層,其輸入通道為16、輸出通道為32。那么一般的操作就是用32個3×3的卷積核來分別同輸入數據卷積,這樣每個卷積核需要3×3×16個參數,得到的輸出是只有一個通道的數據。之所以會得到一通道的數據,是因為剛開始3×3×16的卷積核的每個通道會在輸入數據的每個對應通道上做卷積,然后疊加每一個通道對應位置的值,使之變成了單通道,那么32個卷積核一共需要(3×3×16)×32 =4068個參數。

  用一張來解釋深度可分離卷積,如下: 
這里寫圖片描述 


可以看到每一個通道用一個filter卷積之后得到對應一個通道的輸出,然后再進行信息的融合。而以往標准的卷積過程可以用下面的圖來表示: 
這里寫圖片描述

 

  而應用深度可分離卷積的過程是①用16個3×3大小的卷積核(1通道)分別與輸入的16通道的數據做卷積(這里使用了16個1通道的卷積核,輸入數據的每個通道用1個3×3的卷積核卷積),得到了16個通道的特征圖,我們說該步操作是depthwise(逐層)的,在疊加16個特征圖之前,②接着用32個1×1大小的卷積核(16通道)在這16個特征圖進行卷積運算,將16個通道的信息進行融合(用1×1的卷積進行不同通道間的信息融合),我們說該步操作是pointwise(逐像素)的。這樣我們可以算出整個過程使用了3×3×16+(1×1×16)×32 =656個參數。可以看出運用深度可分離卷積比普通卷積減少了所需要的參數。重要的是深度可分離卷積將以往普通卷積操作同時考慮通道和區域改變成,卷積先只考慮區域,然后再考慮通道。實現了通道和區域的分離。

2、分組卷積

  Group convolution 分組卷積,最早在AlexNet中出現,由於當時的硬件資源有限,訓練AlexNet時卷積操作不能全部放在同一個GPU處理,因此作者把feature maps分給多個GPU分別進行處理,最后把多個GPU的結果進行融合。

  在說明分組卷積之前我們用一張圖來體會一下一般的卷積操作。 
這里寫圖片描述
  從上圖可以看出,一般的卷積會對輸入數據的整體一起做卷積操作,即輸入數據:H1×W1×C1;而卷積核大小為h1×w1,一共有C2個,然后卷積得到的輸出數據就是H2×W2×C2。這里我們假設輸出和輸出的分辨率是不變的。主要看這個過程是一氣呵成的,這對於存儲器的容量提出了更高的要求。 
但是分組卷積明顯就沒有那么多的參數。先用圖片直觀地感受一下分組卷積的過程。對於上面所說的同樣的一個問題,分組卷積就如下圖所示。 
這里寫圖片描述
  可以看到,圖中將輸入數據分成了2組(組數為g),需要注意的是,這種分組只是在深度上進行划分,即某幾個通道編為一組,這個具體的數量由(C1/g)決定。因為輸出數據的改變,相應的,卷積核也需要做出同樣的改變。即每組中卷積核的深度也就變成了(C1/g),而卷積核的大小是不需要改變的,此時每組的卷積核的個數就變成了(C2/g)個,而不是原來的C2了。然后用每組的卷積核同它們對應組內的輸入數據卷積,得到了輸出數據以后,再用concatenate的方式組合起來,最終的輸出數據的通道仍舊是C2。也就是說,分組數g決定以后,那么我們將並行的運算g個相同的卷積過程,每個過程里(每組),輸入數據為H1×W1×C1/g,卷積核大小為h1×w1×C1/g,一共有C2/g個,輸出數據為H2×W2×C2/g。

  從一個具體的例子來看,Group conv本身就極大地減少了參數。比如當輸入通道為256,輸出通道也為256,kernel size為3×3,不做Group conv參數為256×3×3×256。實施分組卷積時,若group為8,每個group的input channel和output channel均為32,參數為8×32×3×3×32,是原來的八分之一。而Group conv最后每一組輸出的feature maps應該是以concatenate的方式組合。 
Alex認為group conv的方式能夠增加 filter之間的對角相關性,而且能夠減少訓練參數,不容易過擬合,這類似於正則的效果。

 

3、空洞(擴張)卷積(Dilated/Atrous Convolution)

  空洞卷積(dilated convolution)是針對圖像語義分割問題中下采樣會降低圖像分辨率、丟失信息而提出的一種卷積思路。利用添加空洞擴大感受野,讓原本3 
x3的卷積核,在相同參數量和計算量下擁有5x5(dilated rate =2)或者更大的感受野,從而無需下采樣。擴張卷積(dilated convolutions)又名空洞卷積(atrous convolutions),向卷積層引入了一個稱為 “擴張率(dilation rate)”的新參數,該參數定義了卷積核處理數據時各值的間距。換句話說,相比原來的標准卷積,擴張卷積(dilated convolution) 多了一個hyper-parameter(超參數)稱之為dilation rate(擴張率),指的是kernel各點之前的間隔數量,【正常的convolution 的 dilatation rate為 1】。

圖說空洞卷積的概念

這里寫圖片描述
(a)圖對應3x3的1-dilated conv,和普通的卷積操作一樣。(b)圖對應3x3的2-dilated conv,實際的卷積kernel size還是3x3,但是空洞為1,需要注意的是空洞的位置全填進去0,填入0之后再卷積即可。【此變化見下圖】(c)圖是4-dilated conv操作。 
在上圖中擴張卷積的感受野可以由以下公式計算得到這里寫圖片描述;其中i+1表示dilated rate。 
比如上圖中(a),dilated=1,F(dilated) = 3×3;圖(b)中,dilated=2,F(dilated)=7×7;圖(c)中,dilated=4, F(dilated)=15×15。 
dilated=2時具體的操作,即按照下圖在空洞位置填入0之后,然后直接卷積就可以了。 
這里寫圖片描述

空洞卷積的動態過程

在二維圖像上直觀地感受一下擴張卷積的過程: 
這里寫圖片描述 
上圖是一個擴張率為2的3×3卷積核,感受野與5×5的卷積核相同,而且僅需要9個參數。你可以把它想象成一個5×5的卷積核,每隔一行或一列刪除一行或一列。 
在相同的計算條件下,空洞卷積提供了更大的感受野。空洞卷積經常用在實時圖像分割中。當網絡層需要較大的感受野,但計算資源有限而無法提高卷積核數量或大小時,可以考慮空洞卷積。

Dilated Convolution感受野指數級增長

對於標准卷積核情況,比如用3×3卷積核連續卷積2次,在第3層中得到1個Feature點,那么第3層這個Feature點換算回第1層覆蓋了多少個Feature點呢? 
第3層: 


這里寫圖片描述 
第2層: 
這里寫圖片描述 
第1層: 
這里寫圖片描述 


第一層的一個5×5大小的區域經過2次3×3的標准卷積之后,變成了一個點。也就是說從size上來講,2層3*3卷積轉換相當於1層5*5卷積。題外話,從以上圖的演化也可以看出,一個5×5的卷積核是可以由2次連續的3×3的卷積代替。 
但對於dilated=2,3*3的擴張卷積核呢? 
第3層的一個點: 


這里寫圖片描述 
第2層: 
這里寫圖片描述 
這里寫圖片描述 

可以看到第一層13×13的區域,經過2次3×3的擴張卷積之后,變成了一個點。即從size上來講,連續2層的3×3空洞卷積轉換相當於1層13×13卷積。

 

轉置卷積和反卷積的區別

那什么是反卷積?從字面上理解就是卷積的逆過程。值得注意的反卷積雖然存在,但是在深度學習中並不常用。而轉置卷積雖然又名反卷積,卻不是真正意義上的反卷積。因為根據反卷積的數學含義,通過反卷積可以將通過卷積的輸出信號,完全還原輸入信號。而事實是,轉置卷積只能還原shape大小,而不能還原value。你可以理解成,至少在數值方面上,轉置卷積不能實現卷積操作的逆過程。所以說轉置卷積與真正的反卷積有點相似,因為兩者產生了相同的空間分辨率。但是又名反卷積(deconvolutions)的這種叫法是不合適的,因為它不符合反卷積的概念。

轉置卷積的動態圖

這里寫圖片描述 


△卷積核為3×3、步幅為2和無邊界擴充的二維轉置卷積 
需要注意的是,轉置前后padding,stride仍然是卷積過程指定的數值,不會改變。

例子

由於上面只是理論的說明了轉置卷積的目的,而並沒有說明如何由卷積之后的輸出重建輸入。下面我們通過一個例子來說明感受下。 
比如有輸入數據:3×3,Reshape之后,為A :1×9,B(可以理解為濾波器):9×4(Toeplitz matrix) 那么A*B=C:1×4;Reshape C=2×2。所以,通過B 卷積,我們從輸入數據由shape=3×3變成了shape=2×2。反過來。當我們把卷積的結果拿來做輸入,此時A:2×2,reshape之后為1×4,B的轉置為4×9,那么A*B=C=1×9,注意此時求得的C,我們就認為它是卷積之前的輸入了,雖然存在偏差。然后reshape為3×3。所以,通過B的轉置 - “反卷積”,我們從卷積結果shape=2×2得到了shape=3×3,重建了分辨率。 
也就是輸入feature map A=[3,3]經過了卷積B=[2,2] 輸出為 [2,2] ,其中padding=0,stride=1,反卷積(轉置卷積)則是輸入feature map A=[2,2],經過了反卷積濾波B=[2,2].輸出為[3,3]。其中padding=0,stride=1不變。那么[2,2]的卷積核(濾波器)是怎么轉化為[4,9]或者[9,4]的呢?通過Toeplitz matrix。 
至於這其中Toeplitz matrix是個什么東西,此處限於篇幅就不再介紹了。但即使不知道這個矩陣,轉置卷積的具體工作也應該能夠明白的。

 

 

 

 

參考資料: 

https://blog.csdn.net/chaolei3/article/details/79374563
https://zhuanlan.zhihu.com/p/28749411 
https://zhuanlan.zhihu.com/p/28186857 
https://blog.yani.io/filter-group-tutorial/ 
https://www.zhihu.com/question/54149221 
http://blog.csdn.net/guvcolie/article/details/77884530?locationNum=10&fps=1 
http://blog.csdn.net/zizi7/article/details/77369945 
https://github.com/vdumoulin/conv_arithmetic 
https://www.zhihu.com/question/43609045/answer/130868981

https://wenku.baidu.com/view/7218f2e6162ded630b1c59eef8c75fbfc77d94bc.html

sobel算子

圖像梯度:算子

 鄭南寧,計算機視覺與模式識別[M]國防工業出版社,1998

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM