Opencv 图像平滑基础二维离散卷积 python API

二维离散卷积

要进行二维离散卷积运算首先需要对矩阵边界进行扩充,opencv提供了函数copyMakeBorder

import cv2
import numpy as np
src = np.array([[5,1,7],[1,5,9],[2,6,2]])
dst = cv2.copyMakeBorder(src,2,2,2,2,cv2.BORDER_REFLECT_101)
dst
array([[2, 6, 2, 6, 2, 6, 2],
       [9, 5, 1, 5, 9, 5, 1],
       [7, 1, 5, 1, 7, 1, 5],
       [9, 5, 1, 5, 9, 5, 1],
       [2, 6, 2, 6, 2, 6, 2],
       [9, 5, 1, 5, 9, 5, 1],
       [7, 1, 5, 1, 7, 1, 5]], dtype=int32)

实现二维离散卷积运算

使用Python的科学计算包Scipy提供的函数:convolve2d(in1m in2m mode = ‘full’, boundary = ‘fill’, fillvalue = 0)

#计算任意卷积核且任意指定的锚点的same卷积
import numpy as np
from scipy import signal
#主函数
if __name__ == "__main__":
    #输入矩阵
    I = np.array([[1,2],[3,4]],np.float32)
    # I 的高和宽
    H1, W1 = I.shape[:2]
    #卷积核
    K = np.array([[-1,-2],[2,1]],np.float32)
    # K的高、宽
    H2, W2 = K.shape[:2]
    #计算full卷积
    c_full = signal.convolve2d(I,K,mode = 'full')
    #指定锚点位置
    kr, kc = 0,0
    #更具锚点位置,从full卷积中截取得到same卷积
    c_same = c_full[H2-kr-1:H1+H2-kr-1,W2-kc-1:W1+W2-kc-1]
    print(c_same)
[[-5. -6.]
 [11.  4.]]

可分离卷积核

一个卷积核至少由两个尺寸比它小的卷积核full卷积而成,并且在计算过程中在所有边界处均进行扩充0的操作

full卷积不满足交换律,但是一维水平方向和一维垂直方向上的卷积核的full卷积是满足交换律的

import numpy as np
from scipy import signal
# 主函数
if __name__ == "__main__":
    kernel1 = np.array([[1,2,3]], np.float32)
    kernel2 = np.array([[4],[5],[6]], np.float32)
    #计算两个核的全卷积
    kernel = signal.convolve2d(kernel1,kernel2,mode = 'full')
    print(kernel)
[[ 4.  8. 12.]
 [ 5. 10. 15.]
 [ 6. 12. 18.]]

离散卷积核的性质

1、full卷积的性质

如果卷积核可以分离则满足结合利率

import numpy as np
from scipy import signal
I = np.array([[1,2,3,10,12],
              [32,43,12,4,190],
              [12,234,78,0,12],
              [43,90,32,8,90],
              [71,12,4,98,123]],np.float32)
K = np.array([[1,0,-1],
              [1,0,-1],
              [1,0,-1]],np.float32)
#计算两者的full卷积
I_Kernel = signal.convolve2d(I,K,mode='full',boundary = 'fill',fillvalue = 0)
print(I_Kernel)

[[   1.    2.    2.    8.    9.  -10.  -12.]
 [  33.   45.  -18.  -31.  187.  -14. -202.]
 [  45.  279.   48. -265.  121.  -14. -214.]
 [  87.  367.   35. -355.  170.  -12. -292.]
 [ 126.  336.  -12. -230.  111. -106. -225.]
 [ 114.  102.  -78.    4.  177. -106. -213.]
 [  71.   12.  -67.   86.  119.  -98. -123.]]
kernel1 = np.array([[1],[1],[1]],np.float32)
kernel2 = np.array([[1,0,-1]],np.float32)
I_k1 = signal.convolve2d(I,kernel1,mode='full',boundary = 'fill',fillvalue = 0)
I_k1_k2 = signal.convolve2d(I_k1,kernel2,mode='full',boundary = 'fill',fillvalue = 0)
print(I_k1_k2)
[[   1.    2.    2.    8.    9.  -10.  -12.]
 [  33.   45.  -18.  -31.  187.  -14. -202.]
 [  45.  279.   48. -265.  121.  -14. -214.]
 [  87.  367.   35. -355.  170.  -12. -292.]
 [ 126.  336.  -12. -230.  111. -106. -225.]
 [ 114.  102.  -78.    4.  177. -106. -213.]
 [  71.   12.  -67.   86.  119.  -98. -123.]]

2、same卷积的性质

讨论一种情况:Kernel的宽和高均为奇数,并且可以分离为水平和垂直方向一维卷积核,则满足结合律,利用此规律可以降低运算量

c_same = signal.convolve2d(I,K,mode='same',boundary = 'fill',fillvalue = 0)
print(c_same)
[[  45.  -18.  -31.  187.  -14.]
 [ 279.   48. -265.  121.  -14.]
 [ 367.   35. -355.  170.  -12.]
 [ 336.  -12. -230.  111. -106.]
 [ 102.  -78.    4.  177. -106.]]
#利用卷积核的分离性进行same卷积运算,且采用0扩充边界,如果不采用0扩充边界卷积结果的上下左右边界的值会不同,在图像处理中可以忽略
c_same1 = signal.convolve2d(I,kernel1,mode='same',boundary = 'fill',fillvalue = 0)
c_same2 = signal.convolve2d(c_same1,kernel2,mode='same',boundary = 'fill',fillvalue = 0)
print(c_same2)
[[  45.  -18.  -31.  187.  -14.]
 [ 279.   48. -265.  121.  -14.]
 [ 367.   35. -355.  170.  -12.]
 [ 336.  -12. -230.  111. -106.]
 [ 102.  -78.    4.  177. -106.]]
posted @ 2019-10-15 09:25  消灭猕猴桃  阅读(234)  评论(0编辑  收藏  举报