在OpenCV里实现高斯平滑4

上面通过代码构造了高斯算子,并且使用二维的卷积运算来平滑图像,也达到了目标,不过还有一个问题,就是当你处理比较大的图片,或者比较大的高斯矩阵时,就会发现计算的时间很长。这时候我们就要考虑有没有高效快速的算法了,再回过头来审视一下二维高斯函数:

在OpenCV里实现高斯平滑4

可以看到最后的等式,再考虑指数的运算法则:

在OpenCV里实现高斯平滑4

根据(1)指数运算公式,反向使用它,就可以变换为两个指数相乘,这样就有意义了,表明高斯算子是可以分离的,并且是可以先作一维的水平的卷积运算,再作一维的垂直的卷积运算,这样的结果是一样的。

下面先来探讨一下卷积计算可分离性,演示的例子如下:

#python 3.7.4,opencv4.1
#蔡军生 https://blog.****.net/caimouse/article/details/51749579
#
import cv2
import numpy as np
import matplotlib.pyplot as plt
from scipy import signal

#计算卷积
image = np.array([[1,2,3],[4,5,6],[7,8,9]])

k1 = np.array([[1],[1],[1]])
k2 = np.array([[1,0,-1]])

k3 = signal.convolve2d(k1, k2)
print(k1,k2,k3)

输出结果如下:

[[1]

 [1]

 [1]]

分离矩阵1

[[ 1  0 -1]]

分离矩阵2

 

[[ 1  0 -1]

 [ 1  0 -1]

 [ 1  0 -1]]

卷积计算后的总矩阵

 

下面来做这样的实验,让一个矩阵先与一维水平方向的卷积运算,再与一维垂直方向上的卷积运算;接着让一个矩阵与二维矩阵卷积运算,代码如下:

#python 3.7.4,opencv4.1
#蔡军生 https://blog.****.net/caimouse/article/details/51749579
#
import cv2
import numpy as np
import matplotlib.pyplot as plt
from scipy import signal

#计算卷积
image = np.array([[1,2,3],[4,5,6],[7,8,9]])

k1 = np.array([[1],[1],[1]])
k2 = np.array([[1,0,-1]])

k3 = signal.convolve2d(k1, k2)
print(k1,k2,k3)

image = np.array([[1,2,3],[4,5,6],[7,8,9]])
#先一维分两次计算
out1 = signal.convolve2d(image, k1)
out2 = signal.convolve2d(out1, k2)
print(out2)

#二维一次计算
out3 = signal.convolve2d(image, k3)
print(out3)

结果输出如下:

[[  1   2   2  -2  -3]

 [  5   7   4  -7  -9]

 [ 12  15   6 -15 -18]

 [ 11  13   4 -13 -15]

 [  7   8   2  -8  -9]]

[[  1   2   2  -2  -3]

 [  5   7   4  -7  -9]

 [ 12  15   6 -15 -18]

 [ 11  13   4 -13 -15]

 [  7   8   2  -8  -9]]

从上面可以看到可分离的卷积核,分为两次一维的计算和一次二维的计算结果是一样的。利用这个性质,就可以加速高斯平滑的计算,因为两次一维的计算量为(图像高度*图像宽度)*(卷积核1高度+卷积核2宽度),而二维的情况计算量为(图像高度*图像宽度)*(卷积核1高度*卷积核2宽度),可以看到一维计算情况要少一些。

https://blog.****.net/caimouse/article/details/51749579

上一篇:golang Map


下一篇:Codeforces Round #585 (Div. 2) A.Yellow Cards