unet详解_Unet 论文解读 代码解读

本文深入解析U-Net网络结构,包括其在FCN基础上的改进,如增加上采样阶段和特征通道,确保上下文信息的完整。此外,文章还介绍了在网络中使用valid卷积和权重损失函数解决细胞分割问题。同时,提供了详细的TensorFlow实现代码,涵盖了卷积、池化、反卷积等关键层的创建。
摘要由CSDN通过智能技术生成

论文解读

network

Architecture:

a. U-net建立在FCN的网络架构上,作者修改并扩大了这个网络框架,使其能够使用很少的训练图像就得到很 精确的分割结果。

b.添加上采样阶段,并且添加了很多的特征通道,允许更多的原图像纹理的信息在高分辨率的layers中进行传播。

c. U-net没有FC层,且全程使用valid来进行卷积,这样的话可以保证分割的结果都是基于没有缺失的上下文特征得到的,因此输入输出的图像尺寸不太一样(但是在keras上代码做的都是same convolution),对于图像很大的输入,可以使用overlap-strategy来进行无缝的图像输出。

tile strategy

d.为了预测输入图像的边缘部分,通过镜像输入图像来外推丢失的上下文(不懂),实则输入大图像也是可以的,但是这个策略基于GPU内存不够的情况下所提出的。

e.细胞分割的另外一个难点在于将相同类别且互相接触的细胞分开,因此作者提出了weighted loss,也就是赋予相互接触的两个细胞之间的background标签更高的权重。

weighted loss

代码解读

layers

初始化weights 和 bias

def weight_variable(shape, stddev=0.1, name="weight"):

initial = tf.truncated_normal(shape, stddev=stddev)

return tf.Variable(initial, name=name)

def weight_variable_devonc(shape, stddev=0.1, name="weight_devonc"):

return tf.Variable(tf.truncated_normal(shape, stddev=stddev), name=name)

def bias_variable(shape, name="bias"):

initial = tf.constant(0.1, shape=shape)

return tf.Variable(initial, name=name)

创建卷积层和池化层

这里的padding使用的是VALID,和论文里面所指出的是一样的。deconv2d是反卷积,也就是upsampling,以第一个upsample为例,输如的x的shape为[None,28,28,1024],则输出的shape为[None,52,52,512]。反卷积的计算细节参考https://blog.csdn.net/nijiayan123/article/details/79416764。

def conv2d(x, W, b, keep_prob_):

with tf.name_scope("conv2d"):

conv_2d = tf.nn.conv2d(x, W, strides=[1, 1, 1, 1], padding='VALID')

conv_2d_b = tf.nn.bias_add(conv_2d, b)

return tf.nn.dropout(conv_2d_b, keep_prob_)

def deconv

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
UNet是一种用于图像分割的卷积神经网络结构,由Ronneberger等人于2015年提出,主要用于医学图像处理中的分割任务。它的结构类似于自编码器,但是在编码器和解码器之间添加了跨层连接,使得网络可以更好地捕捉图像的上下文信息。下面我将为您详细介绍UNet的结构和Python实现。 ## UNet结构 UNet的结构如下图所示: ![unet_architecture](https://cdn.jsdelivr.net/gh/tsy19900929/blog-pic/pic/unet_architecture.png) 可以看到,UNet的结构包括编码器和解码器两部分。 编码器由多个卷积层和池化层组成,用于提取图像的特征信息。每个卷积层都包含一个卷积核和一个激活函数,用于学习特征映射。每个池化层则用于减小特征图的大小,同时增加特征的感受野,以便更好地捕捉图像的上下文信息。 解码器由多个反卷积层和跨层连接组成,用于将编码器学习到的特征信息转化为像素级别的预测结果。每个反卷积层用于将特征图的大小恢复到原始图像的大小,同时保留特征信息。跨层连接则将编码器中相应层的特征图与解码器中相应层的特征图进行连接,以便恢复更细节的信息。最后一层使用sigmoid激活函数将输出转化为0到1之间的概率值,表示每个像素属于前景或背景的概率。 ## Python实现 下面我们使用Python和Keras来实现一个简单的UNet模型。首先需要导入相关的库: ```python from keras.models import Model from keras.layers import Input, concatenate, Conv2D, MaxPooling2D, Conv2DTranspose from keras.optimizers import Adam ``` 接着我们定义编码器和解码器中使用的卷积和反卷积层: ```python def conv2d_block(inputs, filters, kernel_size=(3, 3), activation='relu', padding='same', kernel_initializer='he_normal'): conv = Conv2D(filters, kernel_size, activation=activation, padding=padding, kernel_initializer=kernel_initializer)(inputs) conv = Conv2D(filters, kernel_size, activation=activation, padding=padding, kernel_initializer=kernel_initializer)(conv) return conv def deconv2d_block(inputs, skip_features, filters, kernel_size=(3, 3), activation='relu', padding='same', kernel_initializer='he_normal'): deconv = Conv2DTranspose(filters, kernel_size, strides=(2, 2), padding=padding, kernel_initializer=kernel_initializer)(inputs) deconv = concatenate([deconv, skip_features]) deconv = conv2d_block(deconv, filters, kernel_size=kernel_size, activation=activation, padding=padding, kernel_initializer=kernel_initializer) return deconv ``` 然后我们定义UNet模型: ```python def unet(input_shape=(256, 256, 3), num_classes=1, activation='sigmoid', filters=64, kernel_size=(3, 3), pool_size=(2, 2), kernel_initializer='he_normal'): inputs = Input(input_shape) skip_features = [] # Encoder for filter_num in [filters * (2 ** i) for i in range(4)]: conv = conv2d_block(inputs, filter_num, kernel_size=kernel_size, activation=activation, padding='same', kernel_initializer=kernel_initializer) skip_features.append(conv) pool = MaxPooling2D(pool_size=pool_size)(conv) inputs = pool # Bottleneck bottleneck = conv2d_block(inputs, filters * 16, kernel_size=kernel_size, activation=activation, padding='same', kernel_initializer=kernel_initializer) # Decoder for i, filter_num in enumerate(reversed([filters * (2 ** i) for i in range(4)])): if i == 0: deconv = deconv2d_block(bottleneck, skip_features[-1], filter_num, kernel_size=kernel_size, activation=activation, padding='same', kernel_initializer=kernel_initializer) else: deconv = deconv2d_block(deconv, skip_features[-i-1], filter_num, kernel_size=kernel_size, activation=activation, padding='same', kernel_initializer=kernel_initializer) outputs = Conv2D(num_classes, (1, 1), activation=activation)(deconv) model = Model(inputs=[inputs], outputs=[outputs]) return model ``` 在这个模型中,我们首先定义了编码器和解码器中使用的卷积和反卷积层。然后我们定义了UNet模型,包括输入层、编码器、解码器和输出层。其中编码器和解码器使用了上面定义的卷积和反卷积层。 最后我们使用Adam优化器和二分类交叉熵损失函数来编译模型: ```python model = unet() model.compile(optimizer=Adam(lr=1e-4), loss='binary_crossentropy', metrics=['accuracy']) ``` 这样我们就完成了一个简单的UNet模型的实现。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值