语义分割一般都是使用的全卷积网络,也即可以先提取特征,这时候尺寸会变小,然后会再把尺寸变大到原尺寸,或者说是和训练图片相同的尺寸。因此我们一般需要编码器提取特征,然后再使用解码器恢复尺寸。这里的编码器就是ResNet50
,解码器就是SegNet
。语义分割其实就是对每一个像素进行分类。
一、编码器(ResNet50)
1、它有两个block
,一个是identity_block
,一个是conv_block
。其中,identity_block
内部经过了三次通道变换,由于这是一个残差块,所以经过三次通道变换之后要与输入数据的通道数相同,并且尺寸也要一样,所以在这个block
内部通过我们设置参数并没有使尺寸改变
2、conv_block
内部有四个conv2d
,中间两个都不改变尺寸,只有第一个和第四个可以通过我们设置步幅来改变尺寸。其中第四个conv2d
是直接对输入数据改变尺寸,而不是已经经过三个卷积层的输入数据,这是为了输入数据和已经经过三个conv2d
的数据能够相加,也即通道数和尺寸都一样。
3、然后我们在get_resnet50_encoder
函数里,多次调用这两个block
,然后每压缩一次就赋值给f
,所以最后返回了[f1 , f2 , f3 , f4 , f5 ]
五个特征图。
二、解码器(SegNet)
1、它会对通过编码器提取到的特征进行上采样,在这个例子里,是上采样到原图的(h/2,w/2)
,这和训练数据集,也即已经进行语义分割好的图片的大小是要一样的,因为我们是对每一个像素进行分类。
2、最后解码器的输出是(h/2,w/2,2)
,这里的2
代表像素所属的两个类,要么是0:背景、要么是1:要分割的部分
注意:需要注意的是,训练图片,也就是已经进行过语义分割的图片,其实三个通道的数据是一样的,一个像素位置处的三个通道,要么是(0,0,0),要么是(1,1,1)
,也即不是黑色就是白色。所以其实我们预测的时候可以只预测一个通道就可以了,也即最终的输出是(h/2,w/2,2)
而不是(h/2,w/2,6)
参考工程附上:
https://blog.csdn.net/weixin_44791964/article/details/103244411