本节中首先以代码的形式给出检测网络中高通滤波块的构造过程。
%tensorflow_version 1. x
import os
import tensorflow as tf
from tensorflow. keras.layers import Layer, Input, GlobalAveragePooling2D, Lambda, Dense
from tensorflow. keras.layers import ConvLSTM2D, Conv2D, AveragePool-ing2D, BatchNormalization
from tensorflow. keras.constraints import unit_norm, non_neg
from tensorflow. keras.activations import softmax
from tensorflow. keras.models import Model
from tensorflow. keras.initializers import Constant
from tensorflow. keras.constraints import Constraint
from tensorflow. keras import backend as K
from tensorflow. python.keras.layers.convolutional import Conv
from tensorflow. python.keras.engine import InputSpecimport numpy as np
class Conv2DSymPadding(Conv):
#@interfaces. legacy_conv2d_support
def__init__(self, filters,
kernel_size,
strides=(1,1),
data_format=None,
dilation_rate=(1,1),
activation=None,
padding='same',
use_bias=True,
kernel_initializer='glorot_uniform',
bias_initializer='zeros',
kernel_regularizer=None,
bias_regularizer=None,
activity_regularizer=None,
kernel_constraint=None,
bias_constraint=None,
∗∗kwargs):
super(Conv2DSymPadding, self).__init__(
rank=2,
filters=filters,
kernel_size=kernel_size,
strides=strides,
padding='same',
data_format=data_format,
dilation_rate=dilation_rate,
activation=activation,
use_bias=use_bias,
kernel_initializer=kernel_initializer,
bias_initializer=bias_initializer,
kernel_regularizer=kernel_regularizer,
bias_regularizer=bias_regularizer,
activity_regularizer=activity_regularizer,
kernel_constraint=kernel_constraint,
bias_constraint=bias_constraint,
∗∗kwargs)
self. input_spec=InputSpec(ndim=4)
def get_config(self):
config=super(Conv2DSymPadding, self).get_config()
config. pop('rank')
return config
def call(self, inputs):
if(isinstance(self. kernel_size, tuple)):
kh, kw=self.kernel_size
else:
kh=kw=self.kernel_size
ph, pw=kh//2,kw//2
inputs_pad=tf.pad(inputs,[[0,0],[ph, ph],[pw, pw],[0,0]],mode='symmetric')
outputs=K.conv2d(
inputs_pad,
self. kernel,
strides=self.strides,
padding='valid',
data_format=self.data_format,
dilation_rate=self.dilation_rate)
if self. use_bias:
outputs=K.bias_add(
outputs,
self. bias,
data_format=self.data_format)
if self. activation is not None:
return self. activation(outputs)
return outputs
class BayarConstraint(Constraint):
def__init__(self):
self. mask=None
def_initialize_mask(self, w):
nb_rows, nb_cols, nb_inputs, nb_outputs=K.int_shape(w)
m=np.zeros([nb_rows, nb_cols, nb_inputs, nb_outputs]).astype('float32')
m[nb_rows//2,nb_cols//2]=1.
self. mask=K.variable(m, dtype='float32')
return
def__call__(self, w):
if self. mask is None:
self._initialize_mask(w)
w=w∗(1-self.mask)
rest_sum=K.sum(w, axis=(0,1),keepdims=True)
w/=rest_sum+K.epsilon()
w-=self.mask
return w
class CombinedConv2D(Conv2DSymPadding):
def__init__(self, filters,
kernel_size=(5,5),
strides=(1,1),
data_format=None,
dilation_rate=(1,1),
activation=None,
padding='same',
use_bias=False,
kernel_initializer='glorot_uniform',
bias_initializer='zeros',
kernel_regularizer=None,
bias_regularizer=None,
activity_regularizer=None,
kernel_constraint=None,
bias_constraint=None,
∗∗kwargs):
super(CombinedConv2D, self).__init__(
filters=filters,
kernel_size=(5,5),
strides=strides,
padding='same',(www.xing528.com)
data_format=data_format,
dilation_rate=dilation_rate,
activation=activation,
use_bias=False,
kernel_initializer=kernel_initializer,
bias_initializer=bias_initializer,
kernel_regularizer=kernel_regularizer,
bias_regularizer=None,
activity_regularizer=activity_regularizer,
kernel_constraint=kernel_constraint,
bias_constraint=None,
∗∗kwargs)
self. input_spec=InputSpec(ndim=4)
def_get_srm_list(self):
#srm kernel 1
srm1=np.zeros([5,5]).astype('float32')
srm1[1:-1,1:-1]=np.array([[-1,2,-1],
[2,-4,2],
[-1,2,-1]])
srm1/=4.
#srm kernel 2
srm2=np.array([[-1,2,-2,2,-1],
[2,-6,8,-6,2],
[-2,8,-12,8,-2],
[2,-6,8,-6,2],
[-1,2,-2,2,-1]]). astype('float32')
srm2/=12.
#srm kernel 3
srm3=np.zeros([5,5]).astype('float32')
srm3[2,1:-1]=np.array([1,-2,1])
srm3/=2.
return[srm1,srm2,srm3]
def_build_SRM_kernel(self):
kernel=[]
srm_list=self._get_srm_list()
for idx, srm in enumerate(srm_list):
for ch in range(3):
this_ch_kernel=np.zeros([5,5,3]).astype('float32')
this_ch_kernel[:,:,ch]=srm
kernel. append(this_ch_kernel)
kernel=np.stack(kernel, axis=-1)
srm_kernel=K.variable(kernel, dtype='float32',name='srm')
return srm_kernel
def build(self, input_shape):
if self. data_format=='channels_first':
channel_axis=1
else:
channel_axis=-1
if input_shape[channel_axis]is None:
raise(ValueError,'The channel dimension of the inputs'
'should be defined. FoundNone.')
input_dim=input_shape[channel_axis]
#1. regular conv kernels, fully trainable
filters=self.filters-9-3
if filters>=1:
regular_kernel_shape=self.kernel_size+(input_dim, filters)
self. regular_kernel=self.add_weight(shape=regular_kernel_shape,
initializer=self.kernel_initializer,
name='regular_kernel',
regularizer=self.kernel_regularizer,
constraint=self.kernel_constraint)
print('regular_kernel=',self.regular_kernel.shape)
else:
self. regular_kernel=None
#2. SRM kernels, not trainable
self. srm_kernel=self._build_SRM_kernel()
print('srm_kernel=',self.srm_kernel.shape)
#3. bayar kernels, trainable but under constraint
bayar_kernel_shape=self.kernel_size+(input_dim,3)
self. bayar_kernel=self.add_weight(shape=bayar_kernel_shape,
initializer=self.kernel_initializer,
name='bayar_kernel',
regularizer=self.kernel_regularizer,
constraint=BayarConstraint())
print('bayar_kernel=',self.bayar_kernel.shape)
#4. collect all kernels
if(self. regular_kernel is not None):
all_kernels=[self.regular_kernel,
self. srm_kernel,
self. bayar_kernel]
else:
all_kernels=[self.srm_kernel,
self. bayar_kernel]
self. kernel=K.concatenate(all_kernels, axis=-1)
#Set input spec.
self. input_spec=InputSpec(ndim=self.rank+2,
axes={channel_axis:input_dim})
self. built=True
其中,Conv2DSymPadding给出使用SymPadding的Conv2D层的定义。Ba-yarConstraint类给出一个Bayar的约束,即权重加和为0,中心值为-1,如下式所示。build函数中通过add_weight的constraint参数将这个约束加入卷积层中构成Bayar卷积层。
代码中SRM使用了固定权重的高通滤波层,文中使用了下面的三个滤波核。代码中_get_srm_list函数给出了这三个滤波核。
输入图像为RGB图像,有三个通道。使用K 1、K 2、K 3三个滤波器分别单独处理一个输入通道,共得到九个通道。设O为5×5的零矩阵,这9个通道可以表示为:
以第一个通道为例,对输入的第一个通道使用第一个滤波核K1进行处理,其他两个输入通道置0得到,其他通道类似。代码中_build_SRM_kernel函数给出了该滤波层的构造过程。代码中CombinedConv2D的build函数给出了高通滤波模块的构造过程。这个模块是由9个SRM滤波层和3个BayerConv2d层构成。
框架图中的整个网络模型通过下面的create_model代码构建。使用Com-binedConv2D构造高通滤波块,使用Conv2DSymPadding、AveragePooling2D、Dense和Dropout构成下面的卷积神经网络模块。
from tensorflow. keras.layers import Flatten, Dense, Dropout
def create_model():
base=32
bname='b1'
img_input=Input(shape=(128,128,3),name='image_in')
x=CombinedConv2D(12,activation='relu',use_bias=False, padding='same',name=bname+'c1')(img_input)
x=Conv2DSymPadding(base,(3,3),activation='relu',padding='same',name=bname+'c2')(x)
bname='b2'
nb_filters=32#32
x=Conv2DSymPadding(nb_filters,(3,3),activation='relu',padding='same',name=bname+'c1')(x)
x=AveragePooling2D(pool_size=(3,3),strides=2)(x)
bname='b3'
x=Conv2DSymPadding(nb_filters∗2,(3,3),activation='relu',padding='same',name=bname+'c2')(x)
x=AveragePooling2D(pool_size=(3,3),strides=2)(x)
bname='b4'
x=Conv2DSymPadding(nb_filters∗2,(3,3),activation='relu',padding='same',name=bname+'c2')(x)
x=AveragePooling2D(pool_size=(3,3),strides=2)(x)
x=Flatten(name='flatten')(x)
x=Dense(1024,activation='relu',name='fc1')(x)
x=Dropout(0.5)(x)
x=Dense(2,activation='softmax',name='predictions')(x)
return Model(inputs=[img_input],outputs=[x])
免责声明:以上内容源自网络,版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。