欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

图像处理 之 矩阵一维卷积

程序员文章站 2022-03-24 17:44:32
...

先来几张图认识什么是一维数组卷积:

图像处理 之 矩阵一维卷积

图像处理 之 矩阵一维卷积

图像处理 之 矩阵一维卷积

卷积的应用,图像处理很多地方都会用到卷积运算,具体用在哪方面我也不知道,坐等老师讲解,百度:图像中滤波、均值滤波、锐化等都是在空间域里进行卷积,也就是二维卷积

进入正题,一维数组卷积,用一个例子讲解。

数组 f = [ 0, 1, 2, 3, 4 ] ,g = [0, 1, 2]

设数组h 为 f 和 g 卷积后的结果,则 数组的长度为 len( f ) + len ( g ) – 1 = 7

如下图所示,

图像处理 之 矩阵一维卷积

可以得出:

           Len(h) = Len(f) + Len(g) - 1 

实现此函数

        定义函数 def convolution( f , g ) 为实现数组f 与数组 g的卷积,并将结果数组h返回

def convolution ( f, g):

         #第一步创建并初始化结果数组h

         #使用numpy.zeros( num )函数,其功能主要创建一个长度为num的数组,并将数组数据初始化为0 

         h = numpy.zeros( len(f) + len(g) – 1)   #初始化一个长度为 f和g数组的长度之和-1

 #实现卷积运算,我们将其分为三部分:

         #实现卷积运算,我们将其分为三部分:

         #第一部分为数组g刚开始进入数组f的过程

         #第二部分为数组g在数组f中

         #第三部分为数组g出数组f的过程

 

图像处理 之 矩阵一维卷积

 第一部分:

图像处理 之 矩阵一维卷积

 

                   #即上图k从0到2的状态为第一部分

                   #k从3到4为第二部分

                   #k从5到6为第三部分

                   #首先实现第一部分

                   #由图可知,

图像处理 之 矩阵一维卷积

            for k in range( len(g) ):  
                #range()函数为创建一个数组[0, len(g) ),
                #即0到len(g)的左闭右开数组,此条语句k将依次取该数组元素进行循环,
                #即k从0到len(g) 循环
		h[k] =sum (f[:k+1] * g_[len(g) - 1 - k:])
                #sum(range) 中,range为数组,sum(range)为计算一个数组所有元素之和
                #即sum( [ 1, 2, 3,4 ]) = 10
                #先看f数组   f[:k+1]
                #f[ :k+1] 等价于 f[0:k+1]
                #右下图可知,上标一直在最头部up = 0,而下标为down = k+1

 

图像处理 之 矩阵一维卷积

图像处理 之 矩阵一维卷积

图像处理 之 矩阵一维卷积

                # 再看g_[len(g) - 1 - k:]
                # 首先g函数原本是[0, 1, 2],如图所示,
                #卷积需要将其反转为[2, 1, 0],也就是从右到左,即g_ = g[::-1] = [2, 1, 0]
                #g_数组下标down不变为尾部,头部up 从len(g)-1的位置往前移动k,即up=len(g)-1-k

                                                 所以 h[k] =sum (f[:k+1] * g_[len(g) - 1 - k:])

第二部分:即整个数组g进入数组f

图像处理 之 矩阵一维卷积

图像处理 之 矩阵一维卷积

         第二部分  

 

      for k in range(len(g), len(f)):
            h[k] = sum(f[k + 1 - len(g) : k + 1 ] * g[::-1])

   

第二部中g数组整个数组的所有元素都被用到即 g[::-1]

图像处理 之 矩阵一维卷积

图像处理 之 矩阵一维卷积

再看f[k + 1 - len(g) : k + 1 ]

如上图,f数组与g数组的重合的三个数有效,

先看f数组的下标 down = k+1 此下标与第一部分一样。

因为f数组参加运算元素的长度与g数组长度一样,下标确定,那么上标为up=down-len(g)    即:  up=k+1-len(g)

第一二步理解了第三步也就容易理解了

第三部分:G数组出f数组,

图像处理 之 矩阵一维卷积

图像处理 之 矩阵一维卷积

图像处理 之 矩阵一维卷积

        h[k] = sum(f[k + 1 - len(g):]*g_[: len(g) - (k + 1 - len(f))])

先看g数组,首先取反 即g_=g[::-1]

然后上标不变为最前,下标每次随着k的增大1而减少最尾部1个元素

而在第三部分 k的范围是   len(f) - 1 <k <len(f)+len(g)-1

k增大多少次,尾部减少多少个元素 如和判断k增加了多少,那就是 k-len(f)+1

即减少个范围为   0<k-len(f)+1<len(g)  也就是

减少到只剩下一个元素那么卷积就结束了,整个g数组就出去了

即 原本没减是g’[:len(g)],现在尾部减少k-len(f)+1个元素,

那么就是:g_[: len(g) - (k - len(f) + 1)]

 

f[k + 1 - len(g):]

和 g数组差不多,但是f是取尾部,g数组是取头部

尾部其实和头部道理一样,取头部修改下标,取尾部修改上标,让 k的关系和取得位置对应起来就可以了

原本为 f[len(f)-len(g):len(f)] 现在随着k的增大,数组左边元素减少k-len(f)+1个

即:

f[len(f)-len(g)+(k-len(f)+1):len(f)]=f[k-len(g)+1:]

所以:

h[k] = sum(f[k + 1 - len(g):]*g_[: len(g) - (k - len(f) + 1)])

 

最后返回数组 h

图像处理 之 矩阵一维卷积

完整代码(3个版本):

#这个函数也不重要了,可以理解就可以了,知道是做了什么事情
def conv1d_v0010_kdy(f, g):
    #创建并初始化数组,长度为f数组和g数组长度之和-1,
    h = numpy.zeros((len(f) + len(g) - 1, ))#数组数据都为0
   # g_ = g[::-1]
    
    for k in range(len(g)):
        h[k] = sum(f[:k+1] * g[ -len(g) + k::-1])
        #h[k] =sum (f[:k+1] * g_[len(g) - 1 - k:])
    
    for k in range(len(g), len(f)):
        h[k] = sum(f[k + 1 - len(g) : k + 1 ] * g[::-1])
    
    for k in range(len(f), len(f) + len(g) - 1):
        h[k] = sum(f[k + 1 - len(g):]*g[: k - len(f) - len(g):-1])
        #h[k] = sum(f[k + 1 - len(g):]*g_[: len(g) - (k - len(f) + 1)])
        
    return h
#这个函数也不重要了,可以理解就可以了
#老师这份代码是先把f反转,g不反转,而我做的上面那个是g反转,f不反转,道理是一样的,
#但正常来说应该是g反转,也就是小的数组反转,我问了老师,老师好像是说反转f比较容易讲。。。
def conv1d_v0010(f,g):
    h = numpy.zeros((len(f)+len(g)-1,))
    for k in range(len(g)):
        h[k] = (f[k::-1]*g[:k+1]).sum()
        
    for k in range(len(g), len(f)):
        h[k] = (f[k:k-len(g):-1]*g).sum()
        
    for k in range(len(f), len(h)):
        #h[11] = f[10:9] *g[2:3]=9*2=18
        h[k] = (f[:k-len(g):-1]*g[k-len(f)+1:]).sum()
        
    return h
#最重要的是这个函数
def conv1d(f_, g_):
    #创建卷积后的存放数组
    h = numpy.zeros((len(f_)+len(g_)-1,))
    #反转数组g
    g = g_[::-1]
    
    #创建一个和g数组一模一样大的数组,全部初始化为0
    zeroblock = numpy.zeros_like(g)
    #在f数组前后接上 zeroblock数组   也就是 假使原来数组f为      
    #1, 2, 3, 4   那么接后就是:0, 0,0 ,1,2,3,4,0,0,0
    # 例如 0, 0, 0, 1, 2, 3, 4, 5, 6, 0, 0, 0
    #   与    2,1,0     这样卷积起来就很容易了
    f = numpy.hstack((zeroblock, f_, zeroblock))
    
    #下面就是卷积的操作
    for k in range(len(g_)+len(f_)-1):
        h[k]=(f[k+1:k+1+len(g)]*g).sum()
        
    return h

测试用例:


if __name__ == "__main__":
    f_shape, g_shape = 15, 3
    f, g = numpy.arange(f_shape), numpy.arange(g_shape)
    h = conv1d_v0010(f,g)
    print (h)
    i = conv1d(f,g)
    print (i)
    j = conv1d_v0010_kdy(f, g)
    print (j)
    f, g = numpy.arange(f_shape, f_shape), numpy.arange(g_shape, g_shape)
    

图像处理 之 矩阵一维卷积

(完)