目录

  • 前言
  • 滤波操作
  • 二维滤波(二维卷积)
  • 线性滤波
  • 方框滤波/均值滤波
  • 高斯滤波


前言

滤波分为线性滤波非线性滤波两种,线性滤波中有方框滤波、均值滤波和高斯滤波三种,非线性滤波则有中值滤波和双边滤波两种。在介绍滤波方式之前先以二维滤波的形式介绍滤波的运算。

滤波操作

二维滤波(二维卷积)

用二维滤波的方法选取不同的卷积核可以实现各种不同的效果,虽然OpenCV中内置函数能实现不同的操作,但是通过自己构建卷积核矩阵能够使我们更好的理解不同操作背后的运算逻辑。
将源图像和内核卷积处理,内核kernel(卷积核)是一个浮点数的矩阵,一个5×5的均值滤波内核矩阵如下所示,将内核(卷积核)的中心 与图像的一个像素对齐,5×5的内核则需要将中心周围的25个像素取平均值,并以此值替换中心的像素值,依次对整个图像的其他所有像素操作,便得到了滤波后的图像。
opencv fft滤波 opencv滤波算法_python
首先介绍一下矩阵卷积的计算理论。
离散二维卷积公式:
opencv fft滤波 opencv滤波算法_卷积_02
其中A为被卷积矩阵、B为卷积结果、K为卷积内核。

opencv fft滤波 opencv滤波算法_python_03
将卷积内核K翻转180°
opencv fft滤波 opencv滤波算法_opencv_04
被卷积矩阵A拓展为 (m+2(n%2))x(m+2(n%2)) 的矩阵,在外围无元素位置以0填补
opencv fft滤波 opencv滤波算法_python_05
将K*的中心依次对准A*的元素,相乘后相加
opencv fft滤波 opencv滤波算法_卷积_06
红色部分得出:0+0+0+0+5+8+0+8+5=26 为B(1,1)的值,依次对所有的元素计算,最终得出一个3x3的矩阵,便完成了矩阵的卷积运算。
结果为
opencv fft滤波 opencv滤波算法_卷积_07
下面介绍函数
dst = cv2.filter2D(src, ddepth, kernel, dst=..., anchor=..., delta=..., borderType=...)

参数

介绍

src

输入源图像

ddepth

图像的深度,当值为-1时为和源图像相同

kernal

卷积内核,多取边长为奇数(便于取中心像素点)

dst

计算结果图像有和dst相同的大小和通道数

anchor

内核的锚点,默认为(-1,-1)

delta

卷积过程中会加在每个像素上,默认值为0

borderType

卷积计算时边界的形式,默认为 BORDER_DEAFAULT

anchor 的取值会影响中心像素的位置,默认值(-1,-1)表示锚点位于内核中心。

import cv2
import numpy as np

#读取图片
im1 = cv2.resize(cv2.imread('cat1.jpg',0), None, fx=0.4, fy=0.4, interpolation=cv2.INTER_AREA)

#用Numpy生成了三个内核
#内核1为一个均值滤波的5x5的核
#内核2为一个3x3的边缘检测的核
#内核3为一个对对角线敏感的3x3的核
kernel1 = np.ones((5,5), np.float32)/25
kernel2 = np.mat('-1 -1 -1; -1 8 -1; -1 -1 -1', np.float32)
kernel3 = np.mat('-2 -1 0; -1 0 1; 0 1 2', np.float32)

#分别进行卷积运算
dst1 = cv2.filter2D(im1, -1, kernel1)
dst2 = cv2.filter2D(im1, -1, kernel2)
dst3 = cv2.filter2D(im1, -1, kernel3)

img = [im1, dst1, dst2, dst3]

for i in range(len(img)):
    cv2.imshow('Fig.'+str(i+1), img[i])

k = cv2.waitKey(0)
if k == ord('s'):
    cv2.destroyAllWindows()

opencv fft滤波 opencv滤波算法_计算机视觉_08


图1 二维滤波操作结果

线性滤波

方框滤波/均值滤波

这是最简单的一种滤波方式,方框滤波/均值滤波的作用是模糊一张图片。
使用的是 cv2.boxFilter() 方框滤波和 cv2.blur() 均值滤波
卷积核如下所示
opencv fft滤波 opencv滤波算法_opencv_09
opencv fft滤波 opencv滤波算法_opencv_10
当方框滤波的参数 normalizeTrue 时,方框滤波的内核和均值滤波的内核相同。
dst=cv.boxFilter(src, ddepth, ksize[, dst[, anchor[, normalize[, borderType]]]])

参数

介绍

src

输入源图像,可以有多种通道,不过不同通道之间是分开处理的

ddepth

图像的深度,当值为-1时为和源图像相同

ksize

卷积核的尺寸,如(5,5)

dst

计算结果图像有和dst相同的大小和通道数

anchor

内核的锚点,默认为(-1,-1)表示锚点在卷积核中心

normalize

如上公式所示

borderType

卷积计算时边界的形式,默认为 BORDER_DEAFAULT 一般不管

dst=cv.blur(src, ksize[, dst[, anchor[, borderType]]])

参数

介绍

src

输入源图像,可以有多种通道,不过不同通道之间是分开处理的

ksize

卷积核的尺寸,如(5,5)

dst

计算结果图像有和dst相同的大小和通道数

anchor

内核的锚点,默认为(-1,-1)表示锚点在卷积核中心

borderType

卷积计算时边界的形式,默认为 BORDER_DEAFAULT 一般不管

import cv2
import numpy as np

#读取图片
im1 = cv2.resize(cv2.imread('cat1.jpg',1), None, fx=0.4, fy=0.4, interpolation=cv2.INTER_AREA)
#生成内核卷积与OpenCV的均值模糊相对比
kernal_1 = np.ones((5,5), np.float32)/25

#分别进行卷积运算
dst1 = cv2.blur(im1, (5,5))
dst2 = cv2.boxFilter(im1, -1, (5,5))
dst3 = cv2.filter2D(im1, -1, kernal_1)

img = [im1, dst1, dst2, dst3]

for i in range(len(img)):
    cv2.imshow('Fig.'+str(i+1), img[i])

k = cv2.waitKey(0)
if k == ord('s'):
    cv2.destroyAllWindows()

opencv fft滤波 opencv滤波算法_python_11


图2 生成内核的模糊与均值模糊相对比 右下为生成内核的模糊图

高斯滤波

高斯滤波是一种线性平滑滤波,用来消除高斯噪声效果极佳,通常用于图像的降噪。高斯滤波的卷积运算是一个加权平均的计算过程,其权函数来自正态分布函数,其本质便是图像与正态分布做卷积运算,正态分布也叫高斯分布,因此得名高斯滤波/高斯模糊。
高斯滤波是图像处理中十分常用的一种滤波技术,处理的效果好但是效率并不高。由于高斯函数的傅里叶变换后任为高斯函数,只是幅度和方差发生了变化,所以高斯滤波对于图像来说也是一种低通滤波操作。
一维高斯函数如下:
opencv fft滤波 opencv滤波算法_卷积_12
其中
i 为满足 0<=i<=ksize-1 的整数
α 为使得 ∑G = 1 的一个值
ksize 为卷积核的阶数(长度)
σ 为标准差,通常取1其值越大表示周围的像素点权重越大,也可由下式计算得
opencv fft滤波 opencv滤波算法_opencv fft滤波_13
例如
当卷积核阶数为3时,即 ksize = 3 ,那么 i = 0,1,2
σ=1
则有 G’1=[0.60653 1 0.60653]
通过计算可得
opencv fft滤波 opencv滤波算法_opencv fft滤波_14
最终得出 G1=[0.27410 0.45186 0.27410]
此时得出的为一维的高斯权值
计算二维得高斯模板可以通过 GTG 计算
得:
opencv fft滤波 opencv滤波算法_python_15
在OpenCV中也可以通过 cv2.getGaussianKernal() 来创造高斯卷积核。
dst=cv2.GaussianBlur(src, ksize, sigmaX[, dst[, sigmaY[, borderType]]])

参数

介绍

src

输入源图像,可以有不同的通道,但是不同通道之间是分开处理的

ksize

内核的尺寸,宽度和长度可以不同,但是必须为奇数

sigmaX

X方向上的标准差,与上面 的介绍相同,若取0则由ksize求

sigmaY

Y方向上的标准差,与上面 的介绍相同,若不取值则与sigmaX相等

borderType

图像边缘像素的边界形式

import cv2
import numpy as np
#读取图片
im1 = cv2.resize(cv2.imread('cat1.jpg',1), None, fx=0.4, fy=0.4, interpolation=cv2.INTER_AREA)

#生成5x5的高斯内核与OpenCV的高斯模糊相对比
kernal_1 = np.mat('0.00297 0.01331 0.02194 0.01331 0.00297;\
                    0.01331 0.05963 0.09832 0.05963 0.01331;\
                    0.02194 0.09832 0.16210 0.09832 0.02194;\
                    0.01331 0.05963 0.09832 0.05963 0.01331;\
                    0.00297 0.01331 0.02194 0.01331 0.00297', np.float32)

#分别进行卷积运算
dst1 = cv2.GaussianBlur(im1, (5,5), 1)
#dst2 = cv2.GaussianBlur(im1, (5,5), 0.1)
#dst3 = cv2.GaussianBlur(im1, (5,5), 100)
dst2 = cv2.filter2D(im1, -1, kernal_1)

img = [im1, dst1, dst2]

for i in range(len(img)):
    cv2.imshow('Fig.'+str(i+1), img[i])

k = cv2.waitKey(0)
if k == ord('s'):
    cv2.destroyAllWindows()

代码及结果如下所示,完全相同!

opencv fft滤波 opencv滤波算法_卷积_16


图3 高斯模糊对比 最后还是附一张封面(。ì _ í。)

opencv fft滤波 opencv滤波算法_python_17


最后祝大家学习顺利噢!