矩阵乘法实现卷积运算

1. 对于普通卷积运算,是使用滑动窗口实现卷积运算:

        矩阵根据卷积核的大小进行,从左到右、从上到i的移动,对应数据相乘再相加得到的数据为该区域的值。

​​​​​​​

​​​​​​​

 2.矩阵乘法实现卷积

        原理:根据对于相乘相加的机制,发现通过对卷积核填零构成和输入矩阵大小一致的矩阵,然后展平拼接起来,并且与输入矩阵展平后进行矩阵乘法运算,最后得到的结果和滑动窗口得到的结果一致.

3.两种方式代码进行对比

3.1 滑动窗口卷积

def hua_conv2d(image: np, kernel:np):
    new_image = np.zeros((image.shape[0]-kernel.shape[0]+1,image.shape[1]-kernel.shape[1]+1))
    for i in range(new_image.shape[0]):
        for j in range(new_image.shape[1]):
            new_image[i,j] = np.sum(image[i:i+kernel.shape[0],j:j+kernel.shape[1]]*kernel)
    return new_image

if __name__ == '__main__':
    img = np.array([[1,2,3,4,5,6],
                    [7,8,9,10,11,12],
                    [13,14,15,16,17,18],
                    [19,20,21,22,23,24],
                    [25,26,27,28,29,30],
                    [31,32,33,34,35,36]])
    kernel = np.array([[1,2,3],
                       [4,5,6],
                       [7,8,9]])

    result = hua_conv2d(img,kernel)
    print("result:\n",result)

3.2 矩阵乘法卷积

import numpy as np

# ============ conv2d =======================
def conv2d_(image: np, kernel:np):
    # 将输入矩阵进行横向展平处理
    image_ = np.reshape(image,-1)
    print("image_形状:",image_.shape)

    # 用于存储卷积核填零展平拼接后的矩阵
    dd_ = None
    # 填充零这里使用的是,直接替换全零矩阵的值实现
    '''
        首先需要计算卷积后的到的矩阵大小(w,h)
        通过模仿滑动窗口的样子,依次填充卷积核,最后将它们拼接起来就是一个卷积核矩阵
    '''
    for i in range(image.shape[0]-kernel.shape[0]+1):
        for j in range(image.shape[1]-kernel.shape[1]+1):
            dd = np.zeros(image.shape)  # 根据输入矩阵的大小,来建立全零矩阵
            dd[i:i + kernel.shape[0], j:j + kernel.shape[1]]=kernel # 全零矩阵对应位置被卷积核替换
            if i==0 and j==0:   # 第一个卷积核记录为起点
                dd_ = dd.reshape(-1)[None,:]
            else:
                # 从第二个卷积核开始,进行按行的堆叠
                dd_ = np.concatenate((dd_, dd.reshape(-1)[None,:]),axis=0)
    print("kernels形状:",dd_.shape)
    print("image_的形状:",image_.shape)
    return dd_ @ image_

if __name__ == '__main__':
    img = np.array([[1,2,3,4,5,6],
                    [7,8,9,10,11,12],
                    [13,14,15,16,17,18],
                    [19,20,21,22,23,24],
                    [25,26,27,28,29,30],
                    [31,32,33,34,35,36]])
    kernel = np.array([[1,2,3],
                       [4,5,6],
                       [7,8,9]])

    num = conv2d_(img,kernel)
    # 按照最后的卷积的大小,进行还原
    result = num.reshape(img.shape[0]-kernel.shape[0]+1,img.shape[1]-kernel.shape[1]+1)
    print("result:\n",result)

展示:

 3.3 总结:

        根据这里代码最终的结果,可以看出来,它们的效果是一致的。也就是可以说,我们可以使用矩阵乘法来代替滑动窗口的方式,进而加快运算的效率。  

4.小问题   

        最后代码中,由于卷积核矩阵的构造是用for循环,从而导致最终矩阵乘法这种方式还是很耗时,不过后期小编继续改进的,如果对你有用,请点个赞,谢谢          

  • 9
    点赞
  • 37
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值