本本利用python3实现卷积层的前向传播,提取图像特征。
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Tue May 8 11:22:25 2018
@author: wsw
"""
# convolution implement
import numpy as np
import math
import cv2
import matplotlib.pyplot as plt
def conv2D(x,kernel,stride=1,padding='SAME'):
'''
conv2D implements a convolutional operation on single channel
x:a single channel of input image
kernel:conv kernel
stirde:conv2D stride
padding:default 'SAME'
'''
x_row,x_col = x.shape
k_row,k_col = kernel.shape
if k_row%2==0 or k_col%2==0:
raise Exception('kernel size must be odd')
if padding=='SAME':
# padding input
pad_size_row, pad_size_col = k_row-1, k_col-1
pad_x = np.zeros(shape=(x_row+pad_size_row,x_col+pad_size_col))
id_row = pad_size_row//2
id_col = pad_size_col//2
pad_x[id_row:id_row+x_row,id_col:id_col+x_col] = x
# compute output size
res_row, res_col = math.ceil(x_row/stride), math.ceil(x_col/stride)
res = np.zeros(shape=(res_row,res_col))
# compute conv result
for i in range(0,res_row,stride):
for j in range(0,res_col,stride):
sub = pad_x[i:i+k_row,j:j+k_col]
res[i,j] = np.sum(sub*kernel)
return res
elif padding=='VALID':
# compute output size
res_row = math.ceil((x_row-k_row+1)/stride)
res_col = math.ceil((x_col-k_col+1)/stride)
res = np.zeros((res_row,res_col))
# compute conv result
for i in range(0,res_row,stride):
for j in range(0,res_col,stride):
sub = x[i:i+k_row,j:j+k_col]
res[i,j] = np.sum(sub*kernel)
return res
else:
raise Exception('padding type is not support')
class convLayer():
'''
Construct Convolutional Layer
'''
def __init__(self,in_channels,out_channels,kernel_h,kernel_w):
self.conv_weights = np.random.normal(size=[kernel_h,kernel_w,
in_channels,out_channels])
self.biases = np.zeros(out_channels)
self.in_channels = in_channels
self.out_channels = out_channels
self.kernel_h = kernel_h
self.kernel_w = kernel_w
def forward(self,inputs,stride=1,padding='SAME'):
row, col, channels = inputs.shape
if padding=='SAME':
res_row,res_col = math.ceil(row/stride),math.ceil(col/stride)
else:
res_row = math.ceil((row-self.kernel_h+1)/stride)
res_col = math.ceil((col-self.kernel_w+1)/stride)
res = np.zeros((res_row,res_col,self.out_channels))
for j in range(self.out_channels):
for i in range(self.in_channels):
res[:,:,j] += conv2D(inputs[:,:,i],self.conv_weights[:,:,i,j],
stride=stride,padding=padding)
res[:,:,j] += self.biases[j]
return res
if __name__ == '__main__':
# default 3 channels BGR model
img = cv2.imread('/home/wsw/图片/ha.jpg',cv2.COLOR_BGR2RGB)
img = img/255.0
conv = convLayer(3,1,3,3)
# set specifical kernel
kernel = [[[-1,-2,-1],[0,0,0],[1,2,1]]]
conv.conv_weights[:,:,:,0] = np.tile(kernel,[3,1,1])
res = conv.forward(img)
# display result
plt.subplot(1,2,1)
plt.imshow(img)
plt.title('Original Image')
plt.axis('off')
plt.subplot(1,2,2)
plt.imshow(res[:,:,0],cmap='Greys_r')
plt.title('Feature Map')
plt.axis('off')
plt.show()
特征提取: