前半部分的幾種方法主要將一幅圖像變換成只由邊緣組成的圖像,而后半部分的幾種方法是將圖像輪廓分離出來。當然這篇文章只是我對圖像處理的理解,如果有不妥之處希望大家可以指出來。
卷積
在開始這個專題之前先要講下卷積。寒假剛剛開始看的時候是一臉懵逼的,不太懂卷積是個什么鬼。雖然現在還是不太懂,不過大概懂了這個函數的用處(順便一說,在信號與系統的課本里看到了卷積和拉普拉斯,不知道聽完信號與系統是否對這些計算能有更深入的理解)。我將圖像理解為幾個二維數組的組成。例如YUV圖像,可以理解成三個二維數組,二維數組的坐標代表像素點位置,其值分別代表該點Y、U和V三維的坐標。卷積則是相當于利用不同的卷積規(guī)則實現對圖像的數據計算。后面的幾種算法都是不同的卷積。
梯度和Sobel
導數計算便是一個基本的卷積。最常用來表示微分的操作是Sobel微分算子。在OpenCV中,使用cvSobel()函數實現
cvSobel(
const CvArr *src,
CvArr *dst,
int xorder,
int yorder,
int aperture_size = 3
);
src和dst分別為輸入輸出圖像,xorder和yorder分別代表求導的階數,通常不會超過2。aperture_size表示方形濾波器的寬。在OpenCV 1.0中支持1、3、5、7。
拉普拉斯變換
拉普拉斯函數可以用二次導數的形式定義,在OpenCV中計算拉普拉斯算子時直接使用Sobel算子。
void cvLaplace(
const CvArr *src,
CvArr *dst,
int aperture_size = 3
);
拉普拉斯算子可以用于各種情況,通常的一個應用是檢測團塊。拉普拉斯算子的形式是沿X軸和Y軸二次導數之和,這就意味著周圍值更高的單點或者小塊會將這個函數值最大化,而周圍是更低值的點將會使函數負值最大化。
當我們逼近類似邊緣的不連續(xù)地方時導數會快速增長,而穿過這些不連續(xù)的地方時導數又會快速減小,所以導數在此范圍內會有極值。
Canny算子
Canny算子與拉普拉斯算法不同的地方在于它首先求出x和y方向上的一階導數,然后組合為四個方向上的導數,這些方向導數到達局部最大值的點就是組成邊緣的候選點。
Canny算法最重要的一個新的特點是其仕途將獨立邊的候選像素拼裝成輪廓。輪廓的形成是對這些像素運用滯后性闕值。大于上線闕值會被認為是邊緣像素,小于下限闕值會被拋棄。OpenCV中的函數如下:
void cvCanny(
const CvArr * img,
CvArr * edges,
double lowThresh,
double highThresh,
int aperture_size = 3
lowThresh和highThresh分別代表上下限闕值。