图像处理卷积运算例题,图像的卷积运算
解决问题的传统卷积运算是用滑动窗口在输入图上滑动卷积核,然后乘以当前窗口中相应的元素得到结果,每个窗口得到结果。相乘然后求和恰好也是向量内积的计算方式,这样就可以把每个窗口中的元素引导到向量。如果用向量的内积,那么多个窗口中的向量合并成一个矩阵,每个卷积核也是一个向量,多个卷积核中的向量排列成一个矩阵。因此,卷积运算转化为矩阵乘法。下图是矩阵乘法井的操作过程。
如果将卷积运算转化为矩阵乘法,乘法和加法运算的次数相差不大,但如果转化为矩阵,运算所需的数据存在于连续内存中,因此访问速度大大提高(缓存),矩阵乘法有BLAS、MKL等多种有效的实现方法。
有什么缺点吗?这是在占用和转换更多内存3354的过程中,改变数据冗余存储时间的一种方式。
有两张图片有助于理解:
这里的代码实现使用python的numpy实现。
首先,实现滑动窗口版本。
#!将该语句添加到/usr/wwdkl/env python3 #时,直接在终端命令行模式下输入该文件的名称,文件中的代码# _ * _ coding=UTF-8 _ * _ importnumyang。为了简化运算,默认batch _ size=1 class my _ conv(object):def _ init _(self,input_data,weight_data,sight)padding= same ):self . input=NP . as array(input _ data,NP . float 32)self . weights=NP . as array)weight NP . float 32)self . stride=stride self . padding defmy _ cont w [c,h,w]=self.input.shape [kc,k,_]=self.weights.shape #其中最后,foriinrange(c):f _ map=self . input[I]kernel=self . weights[I]RS=self . compute _ conv)f _ map)kernel(if output==[]:output=RS else:output=rsreturnoutputdefcompute _ conv(self,fm,kernel):[h _]=kernel . shapeifself . padding== same :pad _ h=(self . stride *(h)-2 pad _ w=)self 2rs _ h=hrs _ w=welifself . padding=.
rs=np.zeros([rs_h,rs_w],NP . float 32)for I in range(RS _ h):for J in range(RS _ w):ROI=padding _ FM[I * self . stride:(I * self . stride k),J * self . stride:(J * self . stride k)]RS[I,J]=NP . sum(ROI * kernel)# NP . as array format *是对应元素乘以return rsif _ _ name _= _ _ main _ :input _ data=[[0,J 0],],[ [2,0,2,1,1],[0,1,0,0,2],[1,0,0,2,1],[1,1,2,1,0],[1,0,1,1,1],]Weight _ data=[[1,0,1],[-1,1,0],[0,-1,0],[-1,0,0,1,0],[-1,0,1,1],[0,0,0,1],[1,1,1 矩阵乘法版本实现
#!/usr/wwdkl/env python3 #加上这一句之后,在终端命令行模式下就可以直接输入这个文件的名字后运行文件中的代码# _ * _ coding=utf-8 _ * _ import numpy as NP #为了简化运算,默认batch _ size=1 class my _ conv(object):def _ _ init _ _(self,input_data,weight_data,stride,padding= SAME ):self。输入=NP。作为数组(input _ data,NP。自我漂浮。权重=NP。as数组(weight _ data,NP。自我漂浮。跨步=跨步自我。padding=padding def my _ conv 2d(self): self。输入:c * h * w #输入的数据格式自我。权重:c * h * w [c,h,w]=self.input.shape [kc,k,_]=自重。形状#这里默认卷积核的长宽相等断言c==kc #如果输入的引导与卷积核的引导不一致即报错# rs_h与rs_w为最后输出的特征地图的高与宽如果自我。padding== SAME :pad _ h=(self。stride *(h-1)k-h)//2 pad _ w=(self。stride *(w-1)k-w)//2 RS _ h=h RS _ w=w elif self。padding== VALID :pad _ h=0 pad _ w=0 RS _ h=(h-k)//self。stride 1 RS _ w=(w-k)//self。跨步1 elif自我。padding== FULL :pad _ h=k-1 pad _ w=k-1 RS _ h=(H2 * pad _ h-k)//self。步幅1 RS _ w=(w2 * pad _ w-k)//self。步幅1 #对输入进行补零,注意填料后依然是三维的pad_fm=np.zeros([c,h 2*pad_h,w 2*pad_w),np。范围(c)内I的float 32):pad _ FM[I,pad_h:pad_h h,pad_w:pad_w w]=self.input[i] #将输入和卷积核转化为矩阵相乘的规格mat_fm=np.zeros([rs_h*rs_w,kc*k*k),np。float 32)mat _ kernel=self。权重mat _ kernel。shape=(KC * k * k,1) #转化为列向量row=0 for I in range(RS _ h):for j in range(RS _ w):ROI=pad _ FM[:i*self.stride:(i*self.stride k),j * self。大步:(j * self。步幅k)]mat _ FM[row]=ROI。扁平化()#将投资回收率(investment)的回报利润率(利率)扁平化,即变为行向量row=1 #卷积的矩阵乘法实现rs=np.dot(mat_fm,mat_kernel).整形(rs_h,rs_w)返回rsif _ _ name _ _= _ _ main _ _ :input _ data=[[1,0,1,2,1,0,1],[1,1,0,2,0,2,0],[ [2,0,2,2,1,1,1,1],[0,1,0,0,0,2],[1,0,0,0,0,2,2,2]
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。