目录

一. 语义分割的含义

二. SegNet语义分割模型

三. 基于VGG16主干模型的segnet语义分割

四. 检测结果

五.完整代码


一. 语义分割的含义

语义分割是计算机视觉中的基本任务,在语义分割中我们需要将视觉输入分为不同的语义可解释类别,「语义的可解释性」即分类类别在真实世界中是有意义的。例如,我们可能需要区分图像中属于汽车的所有像素,并把这些像素涂成蓝色。

我们将   图像分类,目标检测  和   语义分割 进行对比 可以让我们更好的理解语义分割。
 图像分类:  通过  提取特征,输出 待测图片趋向于某个种类
 目标检测:   通过  提取特征,输出 待测图片中不同物体的位置与种类 
 语义分割:  通过 提取特征, 输出 待测图片的每个像素点的种类

二. SegNet语义分割模型

SegNet是一种用于语义分割的深度全卷积神经网络结构,其核心由一个编码器网络和一个对应的解码器网络以及一个像素级分类层组成
        如下图所示, 一般的分类,或者检测的特征提取 是通过卷积提取特征, size不断的缩小, 特征维度不断的增高。如同图中的Encoder部分,最后直接接个激活层得出类别信息。 而 语义分割则是在后面跟上 一个Decoder部分, 将前面提取出的高维特征 Size不断增大, 维度不断减少,最后输出的 层的张量直接是 图片的像素点分类结果。

三. 基于VGG16主干模型的segnet语义分割

如上图所示,语义分割模型 分为 编码模型(主干网络)解码模型,主干模型 可以是VGG, ResNet, Mobile等分类及检测模型 , 解码模型有 segnet, unet, pspnet, deeplab等。
        本文代码演示的是基于VGG16的segnet语义分割模型,之后博文里会介绍其他的。完整的模型示意图如下:

左侧是主干模型VGG16,可以看出主干模型并不是完整的VGG16, 而是从靠后的某层抽取出来的。因为完整的VGG16最后输出的是经过激活层之后的确定了种类的特征信息, 而不是单纯的高维特征信息。
Encoder代码如下:

import tensorflow.keras
import tensorflow.keras.backend as K
from tensorflow.keras.activations import *
from tensorflow.keras.layers import *
from tensorflow.keras.models import *IMAGE_ORDERING = 'channels_last'def get_convnet_encoder(input_height=416, input_width=416):img_input = Input(shape=(input_height, input_width, 3))# 416,416,3 -> 208,208,64x = Conv2D(64, (3, 3), activation='relu', padding='same', name='block1_conv1')(img_input)x = Conv2D(64, (3, 3), activation='relu', padding='same', name='block1_conv2')(x)x = MaxPooling2D((2, 2), strides=(2, 2), name='block1_pool')(x)f1 = x# 208,208,64 -> 104,104,128x = Conv2D(128, (3, 3), activation='relu', padding='same', name='block2_conv1')(x)x = Conv2D(128, (3, 3), activation='relu', padding='same', name='block2_conv2')(x)x = MaxPooling2D((2, 2), strides=(2, 2), name='block2_pool')(x)f2 = x# 104,104,128 -> 52,52,256x = Conv2D(256, (3, 3), activation='relu', padding='same', name='block3_conv1')(x)x = Conv2D(256, (3, 3), activation='relu', padding='same', name='block3_conv2')(x)x = Conv2D(256, (3, 3), activation='relu', padding='same', name='block3_conv3')(x)x = MaxPooling2D((2, 2), strides=(2, 2), name='block3_pool')(x)f3 = x# 52,52,256 -> 26,26,512x = Conv2D(512, (3, 3), activation='relu', padding='same', name='block4_conv1')(x)x = Conv2D(512, (3, 3), activation='relu', padding='same', name='block4_conv2')(x)x = Conv2D(512, (3, 3), activation='relu', padding='same', name='block4_conv3')(x)x = MaxPooling2D((2, 2), strides=(2, 2), name='block4_pool')(x)f4 = x# # 在视频中,这个f5并没有用到# # 26,26,512 -> 13,13,512# x = Conv2D(512, (3, 3), activation='relu', padding='same', name='block5_conv1')(x)# x = Conv2D(512, (3, 3), activation='relu', padding='same', name='block5_conv2')(x)# x = Conv2D(512, (3, 3), activation='relu', padding='same', name='block5_conv3')(x)# x = MaxPooling2D((2, 2), strides=(2, 2), name='block5_pool')(x)# f5 = xreturn img_input, f4

Decoder部分代码如下:

from tensorflow.keras.layers import *
from tensorflow.keras.models import *from nets.convnet import get_convnet_encoderdef segnet_decoder(feat, classes_num):# 是否需要重新赋值, feat的原址数据改动是否会造成影响segnet_out = feat#26,26,512 -> 26,26,512segnet_out = ZeroPadding2D((1, 1))(segnet_out)segnet_out = Conv2D(512, (3, 3), padding='valid')(segnet_out)segnet_out = BatchNormalization()(segnet_out)# 26,26,512 -> 52,52,256segnet_out = UpSampling2D((2, 2))(segnet_out)segnet_out = ZeroPadding2D((1, 1))(segnet_out)segnet_out = Conv2D(256, (3, 3), padding='valid')(segnet_out)segnet_out = BatchNormalization()(segnet_out)# 52,52,256 -> 104,104,128segnet_out = UpSampling2D((2, 2))(segnet_out)segnet_out = ZeroPadding2D((1, 1))(segnet_out)segnet_out = Conv2D(128, (3, 3), padding='valid')(segnet_out)segnet_out = BatchNormalization()(segnet_out)# 104,104,128 -> 208,208,64segnet_out = UpSampling2D((2, 2))(segnet_out)segnet_out = ZeroPadding2D((1, 1))(segnet_out)segnet_out = Conv2D(64, (3, 3), padding='valid')(segnet_out)segnet_out = BatchNormalization()(segnet_out)# 208,208,64 -> 208,208,2(classes_num)segnet_out = Conv2D(classes_num, (3, 3), padding='same')(segnet_out)return segnet_outdef convnet_segnet(classes_num, input_height=416, input_width=416, encoder=3):# 从 nets.convent 的 主干网络(vgg部分网络) 导出数据img_input, convnet_out = get_convnet_encoder(input_height, input_width)# 将特征传入segnet网络segnet_out = segnet_decoder(convnet_out, classes_num)# 将 segnet网络输出的结果进行 reshape(x, -1) , -1表示未知# 行:x = int(input_height/2) * int(input_width/2)  列:-1# 注意 这里是  reshape 不是 resizesegnet_out = Reshape((int(input_height/2) * int(input_width/2), -1))(segnet_out)segnet_out = Softmax()(segnet_out)model = Model(img_input, segnet_out)model.model_name = "convent_segnet"return model

四. 检测结果

用上述的模型检测斑马线, 效果如下

五.完整代码

https://github.com/mcuwangzaiacm/VGG16_SegNet_tf2.0

基于VGG16主干模型的segnet语义分割详解及实例相关推荐

  1. 基于深度学习的遥感影像语义分割数据预处理

    基于深度学习的遥感影像语义分割数据预处理 第一次处理数据,不熟练,仅供参考 数据预处理工具:Arcgis 第一步:下载遥感影像tif数据 根据实际需求选择感兴趣的遥感影像区域 数据来源:Google卫 ...

  2. OpenCV语义分割semantic segmentation的实例(附完整代码)

    OpenCV语义分割semantic segmentation的实例 OpenCV语义分割semantic segmentation的实例 OpenCV语义分割semantic segmentatio ...

  3. 毫米波雷达系列 | 基于前后向空间平滑的MUSIC算法详解

    毫米波雷达系列 | 基于前后向空间平滑的MUSIC算法详解 文章目录 毫米波雷达系列 | 基于前后向空间平滑的MUSIC算法详解 DOA阵列模型 MUSIC算法 空间平滑算法 整体流程 仿真代码 忙了 ...

  4. SLIC超像素分割详解

    SLIC超像素分割详解(一) 超像素概念是2003年Xiaofeng Ren提出和发展起来的图像分割技术,是指具有相似纹理.颜色.亮度等特征的相邻像素构成的有一定视觉意义的不规则像素块.它利用像素之间 ...

  5. OSI 七层模型和TCP/IP模型及对应协议(详解)

    OSI 七层模型和TCP/IP模型及对应协议(详解) 查看全文 http://www.taodudu.cc/news/show-6185847.html 相关文章: OSI7层网络模型协议精析 OSI ...

  6. python pptx库中文文档_基于python-pptx库中文文档及使用详解

    个人使用样例及部分翻译自官方文档,并详细介绍chart的使用 一:基础应用 1.创建pptx文档类并插入一页幻灯片 from pptx import Presentation prs = Presen ...

  7. python pptx教学_基于python-pptx库中文文档及使用详解

    个人使用样例及部分翻译自官方文档,并详细介绍chart的使用 一:基础应用 1.创建pptx文档类并插入一页幻灯片 from pptx import Presentation prs = Presen ...

  8. python cv2 轮廓的包络 面积_Python 基于FIR实现Hilbert滤波器求信号包络详解

    在通信领域,可以通过希尔伯特变换求解解析信号,进而求解窄带信号的包络. 实现希尔伯特变换有两种方法,一种是对信号做FFT,单后只保留单边频谱,在做IFFT,我们称之为频域方法:另一种是基于FIR根据传 ...

  9. pandas dataframe数据聚合groupby、agg、privot基于sum统计详解及实例

    pandas dataframe数据聚合groupby.agg.privot基于sum统计详解及实例 知道了sum.那么min.max.mean.median都是举一反三的事情了. 在日常的数据分析中 ...

  10. 基于Java的音频转发服务器_javaCV开发详解之5:录制音频(录制麦克风)到本地文件/流媒体服务器(基于javax.sound、javaCV-FFMPEG)...

    javaCV系列文章: 补充篇: 前言:本篇文章基于javaCV-FFMPEG,关于javaCV官方是没有文档或者api文档可以参考的,所以还有很多地方需要研究: 本章对于ffmpeg的需要有一定了解 ...

最新文章

  1. 只需4步,自己搞个 Spring Boot Starter !
  2. Redis - 事务
  3. 【Flask】在g对象中存放List,实现在捕获异常后继续执行for循环
  4. Asp.Net Core 中IdentityServer4 授权中心之自定义授权模式
  5. javascript中数据访问性能优化简析
  6. iptables学习笔记:端口转发之“外网访问内网”
  7. python容易出错的地方_Python中try-except出错后如何从try出错地方继续执行?
  8. python自动化办公入门书籍-用Python自动办公,做职场高手 | 「讲文兄博客」
  9. got、plt表介绍
  10. 基于Springboot的理财系统
  11. Unity3D游戏开发,适配阿拉伯地区文本显示
  12. 电脑从硬盘启动计算机,如何设置电脑从硬盘启动优先
  13. 紫薇~还记得大明湖畔的HTML5智力拼图吗?
  14. HAL学习笔记 - 7 定时器之基本定时器
  15. python判断字符串包含中文、数字、英文
  16. 「hdu6638」Snowy Smile【稀疏矩阵最大子矩阵和】
  17. echarts在中国地图上绘制各省指标
  18. Python中杨辉三角的理解(廖雪峰教程例)
  19. emlog轩少资源网模板,整站数据源码
  20. CHI Exclusive操作

热门文章

  1. android webview同步,android httpclient与webview cookie同步
  2. webservice服务器框架配置文件,基于Maven环境进行Spring集成CXF WebService框架
  3. 酷狗歌词Krc批量转换工具Lrc [附转换编码DLL]
  4. JavaScript开发环境准备
  5. 边缘计算参考架构3.0
  6. AS/400数据同步专家
  7. FlashBuild4序列号生成与使用方法
  8. android tv 8 安装国内app,不花钱解决 Android TV 原生系统国内APP不显示图标
  9. 华为手机怎么隐藏按键图标_华为手机如何隐藏桌面图标
  10. 从面试官甄别项目经验的角度,说说如何在简历中写项目经验(java后端方向)