图像处理中,"空间域" 指的是图像平面,因此,空间滤波 可定义为:在图像平面内对像素灰度值进行的滤波

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

最新文章

  1. Python3.5之TuShare
  2. C++11 之 nullptr
  3. 【转】Struts2解决表单重复提交问题
  4. BFS+Hash(储存,判重) HDOJ 1067 Gap
  5. 使用Apache ab进行压力测试(参数说明)
  6. django 代码片段3
  7. 2016-6-15-de novo文献阅读
  8. 关于MySQL大牛周振兴的博客
  9. Linux学习笔记(4)-文本编辑器vi的使用
  10. Windows调试工具入门—1
  11. Oracle10 多行和并
  12. 【JMeter】source(&quot;文件路程&quot;)和${变量}同时出现会报错
  13. 记录python接口自动化测试--unittest框架基本应用(第二目)
  14. Struts支持的contentType
  15. 2018-2019 20165221 网络对抗 Exp5 MSF基础
  16. postman连续添加多个订单&amp;jmeter快速审核添加订单
  17. vb.net 多线程運用 ping
  18. 错误:“Manifest merger failed with multiple errors, see logs”
  19. StackOverflow 问题
  20. forEach、for、$.each()跳出循环比较

热门文章

  1. 构建自己的dockerfile
  2. 一次性讲清楚spring中bean的生命周期之三:bean是如何实例化的
  3. Chirp Z-Transform
  4. 【LeetCode】28. 实现 strStr()
  5. IO编程之File类
  6. PO封装设计模式 -- Web页面端测试
  7. Redis中一个String类型引发的惨案
  8. 两万字Vue.js基础学习笔记
  9. PAT乙级:1015 德才论 (25分)
  10. P4334 [COI2007] Policija