OpenCV 之 自定义滤波
图像处理中,"空间域" 指的是图像平面,因此,空间滤波 可定义为:在图像平面内对像素灰度值进行的滤波
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
OpenCV 之 自定义滤波的更多相关文章
- opencv:自定义滤波
卷积核的定义 均值卷积核 // 自定义滤波 - 均值卷积 int k = 15; Mat mkernel = Mat::ones(k, k, CV_32F) / (float)(k * k); Mat ...
- 使用opencv实现自定义卷积
对图像进行卷积是图像处理的基本操作,最近在研究图像滤波,经常要用到自定义卷积,所以实现了一下 #include "opencv2/imgproc/imgproc.hpp" #inc ...
- PIE SDK自定义滤波
1.算法功能简介 自定义滤波可以自由设置滤波模板,对数据进行处理,自定义滤波器的一般规则要求: ( 1) 滤波器的大小应该是奇数,这样它才有一个中心,例如 3x3, 5x5 或者 7x7.有中心了,也 ...
- 目标跟踪之粒子滤波---Opencv实现粒子滤波算法
目标跟踪学习笔记_2(particle filter初探1) 目标跟踪学习笔记_3(particle filter初探2) 前面2篇博客已经提到当粒子数增加时会内存报错,后面又仔细查了下程序,是代码方 ...
- opencv的频域滤波
下面是频域滤波示例程序: 在本程序中,共有五个自定义函数,分别是: 1. myMagnitude(),在该函数中封装了Opencv中的magnitude函数,实现对于复数图像的幅值计算. 2. dft ...
- CUDA加opencv复现导向滤波算法
CUDA是GPU通用计算的一种,其中现在大热的深度学习底层GPU计算差不多都选择的CUDA,在这我们先简单了解下其中的一些概念,为了好理解,我们先用DX11里的Compute shader来和CUDA ...
- opencv中的滤波
以前的时候,为了过滤图像中的一些噪点,学过一些简单的滤波,比如中值滤波,均值滤波,也是自己实现的. 在opencv中有现成的函数可以调用,实现滤波的操作. 函数的原型如下: CVAPI(void) c ...
- 【OpenCV】邻域滤波:方框、高斯、中值、双边滤波
原文:http://blog.csdn.net/xiaowei_cqu/article/details/7785365 邻域滤波(卷积) 邻域算子值利用给定像素周围像素的值决定此像素的最终输出.如 ...
- opencv之图像滤波
均值滤波 均值滤波函数cv2.blur() import cv2 img = cv2.imread('01.jpg') blur = cv2.blur(img,(5,5)) cv2.imshow(&q ...
随机推荐
- XCTF python-trade
一.查看文件类型 后缀名为pyc,说明是python字节码文件,python和java在编译方式上很像,都是编译兼并解释型,先编译成字节码,在虚拟机上解释成机器代码. 二.反编译 三.写个exp 分析 ...
- 密码学系列之:memory-bound函数
密码学系列之:memory-bound函数 目录 简介 内存函数 内存受限函数 内存受限函数的使用 简介 memory-bound函数可以称为内存受限函数,它是指完成给定计算问题的时间主要取决于保存工 ...
- python 字符串 增、删、改、查基本操作
private static String TAG = "MainActivity"; private String str = " a,bB,1cCcc,2dDd d2 ...
- varnish配置语言(1)
目录 1. vcl语法 1.1 主体语法 1.2 操作符 1.3 Subroutines 1.4 关键字 2. 内置的Subroutines 2.1 client-side vcl_recv vcl_ ...
- Java程序设计(2021春)——第三章类的重用笔记与思考
Java程序设计(2021春)--第三章类的重用笔记与思考 本章概览: 3.1 类的继承(概念与语法) 3.2 Object类(在Java继承最顶层的类) 3.3 终结类和终结方法(只能拿来用,不可以 ...
- 锐捷路由器 RSR20-X-28
学习帮助视频 Ruijie#show run | in natip nat outsideip nat insideip nat pool NAT_POOL prefix-length 24ip na ...
- Java基础00-集合进阶26
1. Collection Collection常用方法详解 1.1 集合知识回顾 1.2 集合类体系结构 集合存储数据的方式有单列和双列 Collection中还有List(可以存储可重复的数据)和 ...
- 【16位RAW图像处理三】直方图均衡化及局部直方图均衡用于16位图像的细节增强。
通常我们生活中遇到的图像,无论是jpg.还是png或者bmp格式,一般都是8位的(每个通道的像素值范围是0-255),但是随着一些硬件的发展,在很多行业比如医疗.红外.航拍等一些场景下,拥有更宽的量化 ...
- 前端开发入门到进阶第三集【sublime 的package control ——install package报错】
参考:https://www.cnblogs.com/ae6623/p/5338049.html,解决2帮我解决问题. 解决Sublime包管理package control 报错 There are ...
- PAT乙级:1077 互评成绩计算 (20分)
PAT乙级:1077 互评成绩计算 (20分) 在浙大的计算机专业课中,经常有互评分组报告这个环节.一个组上台介绍自己的工作,其他组在台下为其表现评分.最后这个组的互评成绩是这样计算的:所有其他组的评 ...