影象處理中,"空間域" 指的是影象平面,因此,空間濾波 可定義為:在影象平面內對畫素灰度值進行的濾波

1  空間濾波

1.1  濾波過程

如圖,Filter 是一個 3x3 濾波核,當它從影象的左上角開始,逐個畫素沿水平方向掃描,最後到右下角時,便會產生濾波後的影象

假設輸入影象 $f(x, y)$,濾波後的影象為  $g(x, y)$,則其中 $g(2,2)$ 和 $g(4,4)$ 的計算過程如下:

              

上圖中,以畫素 (4,4) 為中心的 3x3 鄰域,和濾波核的向量點乘之積,即為 g(4,4)

g(4,4) = 240*0.1111 + 183*0.1111 + 0*0.1111 + 250*0.1111 + 12*0.1111 + 87*0.1111 + 255*0.1111 + 1*0.1111 + 94*0.1111

= 26.6666 + 20.3333 + 0 + 27.7777 + 1.3333 + 9.6666 + 28.3333 + 0 + 10.4444

= 124.55

1.2  相關和卷積

空間濾波中,相關和卷積,是容易混淆的概念,定義如下:

-  相關 (Correlation),和上述的濾波過程一樣,即 濾波核 逐行掃描影象,並計算 每個位置畫素點積 的過程

-  卷積 (Convolution),和 "相關" 過程類似,但 濾波核 要 先旋轉 180°,然後再執行和 “相關” 一樣的操作

(二維中的旋轉 180°,等於濾波核沿一個座標軸翻轉,然後再沿另一個座標軸翻轉)

注意:如果濾波核是對稱的,則對影象進行相關和卷積的結果是一致的

2  OpenCV 函式

2.1  filter2D 函式

在 OpenCV 中,可自定義濾波核,然後通過 filter2D() 來完成影象濾波

 void filter2D(
InputArray src, // 輸入影象
OutputArray dst, // 輸出影象(大小和通道數,同 src)
int ddepth, // 輸出影象的 depth
InputArray kernel, // 濾波核,準確地說,是相關核
Point anchor = Point(-1,-1), // 錨點位置,濾波核尺寸為奇數時,不用指定,一般取預設值 Point(-1,-1);濾波核尺寸為偶數時,需指定錨點位置
double delta = 0, // optional value added to the filtered pixels before storing them in dst
int borderType = BORDER_DEFAULT // 邊界處理方法
);

filter2D() 求的是 相關,並非 卷積,只有當濾波核對稱時,filte2D() 才可視為卷積運算,其公式如下:

$\quad dst(x, y) = \sum \limits_{0 \leq x' <kernel.cols, \\ 0 \leq y'<kernel.rows} \: kernel(x', y') * src(x+x'-anchor.x, \; y+y'-anchor.y) $

假定濾波核 kernel 大小為 3x3,以一個畫素點 src(4,4) 為例,則有:

dst(4,4) =   kernel(0,0)*src(4+0-1, 4+0-1) + kernel(0,1)*src(4+0-1, 4+1-1) + kernel(0,2)*src(4+0-1, 4+2-1)

+ kernel(1,0)*src(4+1-1, 4+0-1) + kernel(1,1)*src(4+1-1, 4+1-1) + kernel(1,2)*src(4+1-1, 4+2-1)

+ kernel(2,0)*src(4+2-1, 4+0-1) + kernel(2,1)*src(4+2-1, 4+1-1) + kernel(2,2)*src(4+2-1, 4+2-1)

濾波核與輸入影象的卷積點乘,對應關係如下:

2.2  flip 函式

當濾波核不對稱時,要得到真正的卷積運算,還需 flip() 函式來完成 kernel 的二維翻轉

  void flip(
InputArray src, // input array
OutputArray dst, // output array
int flipCode // 0, flip around x-axis; positive value, flip around y-axis; negative value, flip around both axes.
);

如果濾波核的大小為奇數,則 filter2D() 中的錨點位置可設為 Point(-1,-1),此時,預設濾波核的中心為錨點;如果濾波核的大小為偶數,則需要自定義錨點位置

OpenCV 中錨點位置的實現函式 normalizeAnchor() 如下:

  static inline Point normalizeAnchor(Point anchor, Size ksize)
{
if (anchor.x == -1)
anchor.x = ksize.width / 2;
if (anchor.y == -1)
anchor.y = ksize.height / 2;
CV_Assert(anchor.inside(Rect(0, 0, ksize.width, ksize.height)));
return anchor;
}

3  程式碼示例

3.1  偏導數

自定義濾波核,利用 filter2D() 函式,實現影象的一階和二階偏導運算

 1)  一階偏導

影象在 x 和 y 方向的一階偏導如下:

$\quad \frac {\partial f}{\partial x} = f(x+1,y) - f(x,y)$

$\quad \frac {\partial f}{\partial y} = f(x, y+1) - f(x, y)$

對應濾波核為 $K_{x} = \begin{bmatrix} -1 & 1 \end{bmatrix} $,$K_{y} = \begin{bmatrix} -1 \\ 1 \end{bmatrix} $

    2)  二階偏導

同樣,在 x 和 y 方向的二階偏導如下:

$\quad \frac {\partial f^2} {\partial x^2} = f(x+1, y) + f(x-1, y)- 2f(x,y)$

$\quad \frac {\partial f^2}{\partial y^2} = f(x, y+1) + f(x, y-1)- 2f(x,y)$

$\quad \frac {\partial f^2}{\partial x \partial y} = f(x+1, y+1) - f(x+1, y) - f(x, y+1)+ f(x,y)$

對應濾波核為 $K_{xx} = \begin{bmatrix} 1 & -2 & 1 \end{bmatrix} $,$K_{yy} = \begin{bmatrix} 1 \\ -2 \\ 1 \end{bmatrix} $,$K_{xy} = \begin{bmatrix} 1 & -1 \\ -1 & 1 \end{bmatrix} $

3.2 程式碼示例

#include "opencv2/imgproc.hpp"
#include "opencv2/highgui.hpp" using namespace cv; int main()
{
// 讀取影象
Mat src = imread("fangtze.jpg", IMREAD_GRAYSCALE);
if (src.empty()) {
return -1;
} Mat kx = (Mat_<float>(1, 2) << -1, 1); // 1行2列的 dx 濾波核
Mat ky = (Mat_<float>(2, 1) << -1, 1); // 2行1列的 dy 濾波核 Mat kxx = (Mat_<float>(1, 3) << 1, -2, 1); // 1行3列的 dxx 濾波核
Mat kyy = (Mat_<float>(3, 1) << 1, -2, 1); // 3行1列的 dyy 濾波核
Mat kxy = (Mat_<float>(2, 2) << 1, -1, -1, 1); // 2行2列的 dxy 濾波核 // 一階偏導
Mat dx, dy;
filter2D(src, dx, CV_32FC1, kx);
filter2D(src, dy, CV_32FC1, ky); // 二階偏導
Mat dxx, dyy, dxy;
filter2D(src, dxx, CV_32FC1, kxx);
filter2D(src, dyy, CV_32FC1, kyy);
filter2D(src, dxy, CV_32FC1, kxy); // 顯示影象
imshow("dx", dx); waitKey();
}

輸出的偏導影象如下,第一行從左到右:原圖 - dx - dy;第二行從左至右:dxy - dxx -dyy

    

    

參考資料

OpenCV Tutorials / imgproc module / Making your own linear filters

Gonzalez,《Digital Image Processing》4th  ch3 Intesity Transformations and Spatial Filtering

CS425 Lab: Intensity Transformations and Spatial Filtering