以下内容摘自OpenCV2计算机视觉编程手册
引言
图像滤波是图像处理的一个基本操作,本章介绍几种常用的滤波器和他们的用途。
图像的频率:不同的图像之间的颜色或者灰度分布不同,我们是从分布的角度来看的,如果我们从灰度的变化角度来看,有些图像的灰度变化缓慢,比如一片蓝色的天空,而有些图像灰度变化迅速,比如有很多物品的热闹场景,因此,图像中像素的变化频率构成了另一种描述图像的方式,低频对于图像变化缓慢,高频对应强度变化迅速,滤波的操作就是针对图像某一频段进行操作的。
使用低通滤波器模糊图像
- 目的:使用低通滤波器能够降低图像变化的幅度,即滤除高频成分。
- 函数:cv::blur(…)或cv::GaussianBlur(…)
- 原理:将每个像素替换为相邻矩形内像素的平均值。
这类滤波器被称为箱式滤波器,滤波过程是:给定一个核(矩阵),矩阵的元素是权重,核沿着图像的每一个像素移动,该像素与矩阵的中心元素对齐,然后把矩阵每个权重和它覆盖的像素值相乘,最后相加,这一个过程也就是卷积的过程。
GaussianBlur()函数的核是一个高斯核,权重由一维高斯函数计算得到。
如果想要在图像中应用二维高斯滤波,可以先对行应用一维高斯滤波,再对列应用一维高斯滤波。
使用中值滤波器去除椒盐噪声
- 目的:去除图像中的椒盐噪声(分散的雪花点),也会去除图像中的一些纹理。
- 函数:medianBlur()
- 原理:使用每一个像素邻域中所有像素的中值代替当前像素值,如果区域中有黑色或者白色的噪点,就会被其他像素代替。
使用方向滤波器检测边缘
方向滤波器实际上是一种高频滤波器,具有方向性,利用核对所有像素进行卷积操作,反映图像强度的变化程度。
如果选取Sobel核,则滤波器被称为Sobel滤波器。
水平方向滤波的核选为:
-1 | 0 | 1 |
---|---|---|
-2 | 0 | 2 |
-1 | 0 | 1 |
垂直方向滤波的核选为:
-1 | -2 | -1 |
---|---|---|
0 | 0 | 0 |
1 | 2 | 1 |
从Sobel的核可以看出,Sobel算子能够计算出每个像素水平或垂直方向的梯度(变化量),相当于图像函数的一阶导数,使用其可以实现边缘检测。
检测边缘的步骤如下:
- 对图像先后在X和Y方向上应用Sobel滤波器,结果要保存在16位有符号整数图像中
- 计算两个输出图像之间的L1距离,即像素的绝对值之和,因为比L2距离的复杂度低。
- 将上一步得到的图像线性变换为8位整数图像。
- 最后将上一步图像二值化就能够清除看到黑色的轮廓了,选择合适的阈值非常难,太大会导致破碎的边,太小导致边缘太多。
其他算子
还有其他的梯度算子,如:Prewitt算子,Roberts算子,Scharr算子。
拉普拉斯变化检测边缘
拉普拉斯变换后的像素为X方向和Y方向的二阶导数之和,用于衡量图像的弯曲度,它的核如下所示:
0 | 1 | 0 |
---|---|---|
1 | -4 | 1 |
0 | 1 | 0 |
我们来看一下边缘处图像曲率的变化,因为边缘处图像的灰度区间发生了快速的变化(比如:从暗处到明处),这时,图像的曲率就会从正曲率变化为负曲率,或者从负曲率变化为正曲率,曲率值符号改变出就是边缘所在处。
因此,根据这个原理就可以进行边缘检测,步骤如下:
- 计算Laplace变化,函数为:cv::Laplacian(…),输出图像为32位有符号浮点数。
- 新建一个同样大小的白色二值图像,用于保存边缘信息。
- 创建两张图像的迭代器,如果相邻像素(当前像素与上方像素及当前像素与左方像素)乘积小于0,则将二值图像中的像素设置为黑色
可以将0变为负数的阈值,确保当前的像素值能被认为是一条边,该算法的缺点就是检测到的边缘太多,强边和弱边无法区分,并且对噪点非常敏感,