前言
本文主要基于UNet的网络结构搭建
配合文章:语义分割框架链接
一、UNet官网图
二、UNet代码实现
class UNet(chainer.Chain):
def __init__(self, class_num,alpha=1,initialW=None):
super(UNet, self).__init__()
self.alpha=alpha
if initialW is None:
initialW = chainer.initializers.HeNormal()
with self.init_scope():
self.conv1_1 = L.Convolution2D(None, 64//self.alpha, 3, 1, 1, nobias=True, initialW=initialW)
self.conv1_1_bn = L.BatchNormalization(64//self.alpha, initial_beta=0.001)
self.conv1_2 = L.Convolution2D(64//self.alpha, 64//self.alpha, 3, 1, 1, nobias=True, initialW=initialW)
self.conv1_2_bn = L.BatchNormalization(64//self.alpha, initial_beta=0.001)
self.conv2_1 = L.Convolution2D(64//self.alpha, 128//self.alpha, 3, 1, 1, nobias=True, initialW=initialW)
self.conv2_1_bn = L.BatchNormalization(128//self.alpha, initial_beta=0.001)
self.conv2_2 = L.Convolution2D(128//self.alpha, 128//self.alpha, 3, 1, 1, nobias=True, initialW=initialW)
self.conv2_2_bn = L.BatchNormalization(128//self.alpha, initial_beta=0.001)
self.conv3_1 = L.Convolution2D(128//self.alpha, 256//self.alpha, 3, 1, 1, nobias=True, initialW=initialW)
self.conv3_1_bn = L.BatchNormalization(256//self.alpha, initial_beta=0.001)
self.conv3_2 = L.Convolution2D(256//self.alpha, 256//self.alpha, 3, 1, 1, nobias=True, initialW=initialW)
self.conv3_2_bn = L.BatchNormalization(256//self.alpha, initial_beta=0.001)
self.conv4_1 = L.Convolution2D(256//self.alpha, 512//self.alpha, 3, 1, 1, nobias=True, initialW=initialW)
self.conv4_1_bn = L.BatchNormalization(512//self.alpha, initial_beta=0.001)
self.conv4_2 = L.Convolution2D(512//self.alpha, 512//self.alpha, 3, 1, 1, nobias=True, initialW=initialW)
self.conv4_2_bn = L.BatchNormalization(512//self.alpha, initial_beta=0.001)
self.conv5_1 = L.Convolution2D(512//self.alpha, 1024//self.alpha, 3, 1, 1, nobias=True, initialW=initialW)
self.conv5_1_bn = L.BatchNormalization(1024//self.alpha, initial_beta=0.001)
self.conv5_2 = L.Convolution2D(1024//self.alpha, 512//self.alpha, 3, 1, 1, nobias=True, initialW=initialW)
self.conv5_2_bn = L.BatchNormalization(512//self.alpha, initial_beta=0.001)
self.conv6_1 = L.Convolution2D(1024//self.alpha, 512//self.alpha, 3, 1, 1, nobias=True, initialW=initialW)
self.conv6_1_bn = L.BatchNormalization(512//self.alpha, initial_beta=0.001)
self.conv6_2 = L.Convolution2D(512//self.alpha, 256//self.alpha, 3, 1, 1, nobias=True, initialW=initialW)
self.conv6_2_bn = L.BatchNormalization(256//self.alpha, initial_beta=0.001)
self.conv7_1 = L.Convolution2D(512//self.alpha, 256//self.alpha, 3, 1, 1, nobias=True, initialW=initialW)
self.conv7_1_bn = L.BatchNormalization(256//self.alpha, initial_beta=0.001)
self.conv7_2 = L.Convolution2D(256//self.alpha, 128//self.alpha, 3, 1, 1, nobias=True, initialW=initialW)
self.conv7_2_bn = L.BatchNormalization(128//self.alpha, initial_beta=0.001)
self.conv8_1 = L.Convolution2D(256//self.alpha, 128//self.alpha, 3, 1, 1, nobias=True, initialW=initialW)
self.conv8_1_bn = L.BatchNormalization(128//self.alpha, initial_beta=0.001)
self.conv8_2 = L.Convolution2D(128//self.alpha, 64//self.alpha, 3, 1, 1, nobias=True, initialW=initialW)
self.conv8_2_bn = L.BatchNormalization(64//self.alpha, initial_beta=0.001)
self.conv9_1 = L.Convolution2D(128//self.alpha, 64//self.alpha, 3, 1, 1, nobias=True, initialW=initialW)
self.conv9_1_bn = L.BatchNormalization(64//self.alpha, initial_beta=0.001)
self.conv9_2 = L.Convolution2D(64//self.alpha, 64//self.alpha, 3, 1, 1, nobias=True, initialW=initialW)
self.conv9_2_bn = L.BatchNormalization(64//self.alpha, initial_beta=0.001)
self.conv_classifier = L.Convolution2D(64//self.alpha, class_num, 1, 1, 0, initialW=initialW)
def _upsampling_2d(self, x, indices):
if x.shape != indices.shape:
min_h = min(x.shape[2], indices.shape[2])
min_w = min(x.shape[3], indices.shape[3])
x = x[:, :, :min_h, :min_w]
indices = indices[:, :, :min_h, :min_w]
outsize = (x.shape[2] * 2, x.shape[3] * 2)
return F.upsampling_2d(x, indices, ksize=2, stride=2, outsize=outsize)
def __call__(self, x):
return self.forward(x)
def forward(self, x):
h = F.relu(self.conv1_1_bn(self.conv1_1(x)))
h1 = F.relu(self.conv1_2_bn(self.conv1_2(h)))
h, indices1 = F.max_pooling_2d(h1, 2, 2, return_indices=True)
h = F.relu(self.conv2_1_bn(self.conv2_1(h)))
h2 = F.relu(self.conv2_2_bn(self.conv2_2(h)))
h, indices2 = F.max_pooling_2d(h2, 2, 2, return_indices=True)
h = F.relu(self.conv3_1_bn(self.conv3_1(h)))
h3 = F.relu(self.conv3_2_bn(self.conv3_2(h)))
h, indices3= F.max_pooling_2d(h3, 2, 2, return_indices=True)
h = F.relu(self.conv4_1_bn(self.conv4_1(h)))
h4 = F.relu(self.conv4_2_bn(self.conv4_2(h)))
h, indices4= F.max_pooling_2d(h4, 2, 2, return_indices=True)
h = F.relu(self.conv5_1_bn(self.conv5_1(h)))
h5 = F.relu(self.conv5_2_bn(self.conv5_2(h)))
h = self._upsampling_2d(h5, indices4)
h = F.concat((h, h4))
h = F.relu(self.conv6_1_bn(self.conv6_1(h)))
h = F.relu(self.conv6_2_bn(self.conv6_2(h)))
h = self._upsampling_2d(h, indices3)
h = F.concat((h, h3))
h = F.relu(self.conv7_1_bn(self.conv7_1(h)))
h = F.relu(self.conv7_2_bn(self.conv7_2(h)))
h = self._upsampling_2d(h, indices2)
h = F.concat((h, h2))
h = F.relu(self.conv8_1_bn(self.conv8_1(h)))
h = F.relu(self.conv8_2_bn(self.conv8_2(h)))
h = self._upsampling_2d(h, indices1)
h = F.concat((h, h1))
h = F.relu(self.conv9_1_bn(self.conv9_1(h)))
h = F.relu(self.conv9_2_bn(self.conv9_2(h)))
out = self.conv_classifier(h)
return out
三.调用方法
model = UNet(class_num=len(self.classes_names),alpha=self.alpha)
self.model = PixelwiseSoftmaxClassifier(model)
if self.gpu_devices>=0:
chainer.cuda.get_device_from_id(self.gpu_devices).use()
self.model.to_gpu()