every blog every motto: You will never know unless you try

0. 前言

本文旨在讲解有关语义分割的基础内容,并进行实战。

1. 正文

1.1 前提梗概

1.1.1 引言

不要强求不可知,要从已知推未知
为了更好的了解语义分割,会先简单回顾一下作为深度学习“Hello World ”的mnist / fashion-mnist

1.1.2 mnist / fashion_mnsit

mnist是一个手写数字识别的数据集,一张图像上只有一个数字,如下图所示


上面每张图片即是一个原图/样本(x),他的标签是对应数字的字符(y / label)

主要任务是分类,即对识别每张图片的数字!
有关fashion_mnist数据集也是类似,具体可参考想看就点我
总结: mnist/fashion_mnist ,原图 / 训练样本(x)是一张仅含一种物体的图片,标签(y) 是一个字符或者说one_hot编码。对其处理也较为简单,属于分类任务

1.2 语义分割基础

1.2.1 概念

  • 直观理解:
    一言以蔽之: 是将一张(含有多种物体的)图片,识别出其中的每一种物体。
    语义分割的直观理解,如下图所示。

    动画理解(实际意义):

    最简单的语义分割,当属于“二分类”,即识别出图片中的两种地物,一种归为背景,另一种归为想要提取的物体(如我们接下来要说的斑马线)
  • 进一步理解:
    我们以遥感影像为例,如下图所示:
    左边是原图/样本(x),右图是标签(label,黑色的是背景,红色的是标注的建筑物)
    注: 标注自己的训练样本
    这里的标签是一张图片,不同于mnsit(标签是一个字符串)
    这里的标签是一张图片,不同于mnsit(标签是一个字符串)
    这里的标签是一张图片,不同于mnsit(标签是一个字符串)
  • 更进一步理解:
    通过如下过程,不断计算损失函数,调整参数,直至loss函数最小,即参数最优为止。
  • 深入理解:
    整个网络如下图所示,分为两部分,分别是编码、解码部分。

    图像shape的变化:
    编码:图像(size)不断变小,同时不断变厚(通道数增加)
    解码:图像(size)不断变大(最终恢复到原图的1/2),同时不断变薄(通道数减小)

1.2.2 网络结构

说明: 网络结构如下图所示,但其中size和shape的具体数字与代码中不对,原因是我用此网络跑了其他的图片,也是基于别的图片画的网络结构,由此可以看出,各输入图片经过模型后,各特征图的缩放比例没有变化,在于初始大小不同而已。

链接: 用Plotneuralnet画神经网络图

1.2.3 结果展示

使用下方代码,进行预测,最终结果。
原图:

预测结果:
可以发现,基本将斑马线标出,由于训练数据(191个)较少,有这样的结果还算不错。

1.3 代码部分

说明: 具体代码,文后附链接。

1.3.1 模型部分(model.py)

主函数如下:
如上所说,模型分为两部分,编码、解码。

def main():"""model 的主程序,语义分割,分为两部分,第一部分特征提取,第二部分放大图片:param Height: 图片长:param Width: 图片宽:return: (H,W,3) -> (h,w,2)"""# 第一部分 编码,提取特征,图像size减小,通道增加img_input, feature_map_list = encoder(input_height=Height, input_width=Width)# 第二部分 解码,将图像上采样,size放大,通道减小output = decoder(feature_map_list, class_number=class_number, input_height=Height, input_width=Width,encoder_level=3)# 构建模型model = Model(img_input, output)# model.summary()print('模型输入shape:', img_input.shape, '模型输出图像shape:', output.shape)print('-'*100)return model

模型的前半部分,编码部分:
下采样过程,下采样包括卷积和池化。
基于VGG16的编码网络,用于提取特征,有关卷积运算可参考文章1、文章2

def encoder(input_height, input_width):"""语义分割的第一部分,特征提取,主要用到VGG网络,函数式API:param input_height: 输入图像的长:param input_width: 输入图像的宽:return: 返回:输入图像,提取到的5个特征"""# 输入img_input = Input(shape=(input_height, input_width, 3))# print('--')# print(img_input.shape)# 三行为一个结构单元,size减半# 416,416,3 -> 208,208,64,x = Conv2D(64, (3, 3), activation='relu', padding='same')(img_input)x = Conv2D(64, (3, 3), activation='relu', padding='same')(x)x = MaxPool2D((2, 2), strides=(2, 2))(x)f1 = x  # 暂存提取的特征# 208,208,64 -> 104,104,128x = Conv2D(128, (3, 3), activation='relu', padding='same')(x)x = Conv2D(128, (3, 3), activation='relu', padding='same')(x)x = MaxPool2D((2, 2), strides=(2, 2))(x)f2 = x  # 暂存提取的特征# 104,104,128 -> 52,52,256x = Conv2D(256, (3, 3), activation='relu', padding='same')(x)x = Conv2D(256, (3, 3), activation='relu', padding='same')(x)x = Conv2D(256, (3, 3), activation='relu', padding='same')(x)x = MaxPool2D((2, 2), strides=(2, 2))(x)f3 = x  # 暂存提取的特征# 52,52,256 -> 26,26,512x = Conv2D(512, (3, 3), activation='relu', padding='same')(x)x = Conv2D(512, (3, 3), activation='relu', padding='same')(x)x = Conv2D(512, (3, 3), activation='relu', padding='same')(x)x = MaxPool2D((2, 2), strides=(2, 2))(x)f4 = x  # 暂存提取的特征# 26,26,512 -> 13,13,512x = Conv2D(512, (3, 3), activation='relu', padding='same')(x)x = Conv2D(512, (3, 3), activation='relu', padding='same')(x)x = Conv2D(512, (3, 3), activation='relu', padding='same')(x)x = MaxPool2D((2, 2), strides=(2, 2))(x)f5 = x  # 暂存提取的特征# print(img_input.shape[1:])return img_input, [f1, f2, f3, f4, f5]

模型的后半部分,解码部分:
上采样过程,
关于模型后半部分的经过softmax的理解,2020.9.26添加

def decoder(feature_map_list, class_number, input_height=416, input_width=416, encoder_level=3):"""语义分割的后半部分,上采样,将图片放大,:param feature_map_list: 特征图(多个),encoder得到:param class_number: 分类数:param input_height: 输入图像长:param input_width: 输入图像宽:param encoder_level: 利用的特征图,这里利用f4:return: output , 返回放大后的特征图 (208*208,2)"""# 获取一个特征图,特征图来源encoder里面的f1,f2,f3,f4,f5; 这里获取f4feature_map = feature_map_list[encoder_level]# 解码过程 ,以下 (26,26,512) -> (208,208,64)# f4.shape=(26,26,512) -> 26,26,512x = ZeroPadding2D((1, 1))(feature_map)x = Conv2D(512, (3, 3), padding='valid')(x)x = BatchNormalization()(x)# 上采样,图像长宽扩大2倍,(26,26,512) -> (52,52,256)x = UpSampling2D((2, 2))(x)x = ZeroPadding2D((1, 1))(x)x = Conv2D(256, (3, 3), padding='valid')(x)x = BatchNormalization()(x)# 上采样,图像长宽扩大2倍 (52,52,512) -> (104,104,128)x = UpSampling2D((2, 2))(x)x = ZeroPadding2D((1, 1))(x)x = Conv2D(128, (3, 3), padding='valid')(x)x = BatchNormalization()(x)# 上采样,图像长宽扩大2倍,(104,104,128) -> (208,208,64)x = UpSampling2D((2, 2))(x)x = ZeroPadding2D((1, 1))(x)x = Conv2D(64, (3, 3), padding='valid')(x)x = BatchNormalization()(x)# 再进行一次卷积,将通道数变为2(要分类的数目) (208,208,64) -> (208,208,2)x = Conv2D(class_number, (3, 3), padding='same')(x)# print(x.shape)# reshape: (208,208,2) -> (208*208,2)# y = Reshape((208,208,-1))(x)# print('y shape:',y.shape)x = Reshape((int(input_height / 2) * int(input_width / 2), -1))(x)# print(x.shape)# 求取概率output = Softmax()(x)return output

网络结构,summary:

1.3.2 训练部分(train.py)

主函数,如下:

def main():# 获取已建立的模型,并加载官方与训练参数,模型编译model = get_model()# 打印模型摘要# model.summary()# 获取样本(训练集&验证集) 和标签的对应关系,trian_num,val_numlines, train_nums, val_nums = get_data()# 设置回调函数 并返回保存的路径callbacks, logdir = set_callbacks()# 生成样本和标签# generate_arrays_from_file(lines, batch_size=batch_size)# 训练model.fit_generator(generate_arrays_from_file(lines[:train_nums], batch_size),steps_per_epoch=max(1, train_nums // batch_size),epochs=50, verbose=1, callbacks=callbacks,validation_data=generate_arrays_from_file(lines[train_nums:], batch_size),validation_steps=max(1, val_nums // batch_size),initial_epoch=0)save_weight_path = os.path.join(logdir, 'last.h5')  # 保存模型参数的路径model.save_weights(save_weight_path)

1.3.3 预测部分(predict.py)

axis参数辨析,点我
主函数,如下:

def main():""" 模型预测"""model = get_model()predicting(model)

1.4 源码及视频讲解

1.4.1 源码

https://github.com/onceone/Semantic-segmentation
数据集:提取码pp6w —>数据集来源

1.4.2 视频讲解

感谢评论区shu_0233的指出。
https://www.bilibili.com/video/BV1Bi4y1G7PE?from=search&seid=9616538879256765990


知识无价,如果帮助到你,不妨请喝一杯奶茶~~

参考文献

[1] https://blog.csdn.net/weixin_39190382/article/details/105890812
[2] https://blog.csdn.net/weixin_44791964/article/details/102979289
[3] https://baijiahao.baidu.com/s?id=1602428106371812559&wfr=spider&for=pc
[4] https://blog.csdn.net/weixin_40446557/article/details/85624579
[5] https://www.sohu.com/a/301097998_120054440
[6] https://www.cnblogs.com/xianhan/p/9145966.html
[7] https://blog.csdn.net/weixin_39190382/article/details/105692853
[8] https://blog.csdn.net/weixin_39190382/article/details/105702100
[9] https://blog.csdn.net/weixin_39190382/article/details/104083347
[10] https://blog.csdn.net/weixin_39190382/article/details/108803650

【Tensorflow2】语义分割实战1---斑马线识别相关推荐

  1. 视频教程-U-Net图像语义分割实战:训练自己的数据集-计算机视觉

    U-Net图像语义分割实战:训练自己的数据集 大学教授,美国归国博士.博士生导师:人工智能公司专家顾问:长期从事人工智能.物联网.大数据研究:已发表学术论文100多篇,授权发明专利10多项 白勇 ¥8 ...

  2. 深度学习实战23(进阶版)-语义分割实战,实现人物图像抠图的效果(计算机视觉)

    大家好,我是微学AI,今天给大家带来深度学习实战23(进阶版)-语义分割实战,实现人物图像抠图的效果.语义分割是计算机视觉中的一项重要任务,其目标是将图像中的每个像素都分配一个语义类别标签.与传统的目 ...

  3. DeepLabV3+语义分割实战

    DeepLabV3+语义分割实战 语义分割是计算机视觉的一项重要任务,本文使用Jittor框架实现了DeepLabV3+语义分割模型. DeepLabV3+论文:https://arxiv.org/p ...

  4. 视频教程-DeepLabv3+图像语义分割实战:训练自己的数据集-计算机视觉

    DeepLabv3+图像语义分割实战:训练自己的数据集 大学教授,美国归国博士.博士生导师:人工智能公司专家顾问:长期从事人工智能.物联网.大数据研究:已发表学术论文100多篇,授权发明专利10多项 ...

  5. 语义分割实现地表建筑物识别1

    通过对遥感技术获取的航拍图进行计算机视觉识别可以获取植被面积.建筑物检测等地表覆盖信息,是一项高效且意义重大的任务.本次任务是根据航拍图识别图片中的地表建筑具体像素位置. 知识准备--简述语义分割与其 ...

  6. 天池赛题解析:零基础入门语义分割-地表建筑物识别-CV语义分割实战(附部分代码)

    赛题内容 赛题背景 赛题以计算机视觉为背景,要求选手使用给定的航拍图像训练模型并完成地表建筑物识别任务.为更好的引导大家入门,我们为本赛题定制了学习方案和学习任务,具体包括语义分割的模型和具体的应用案 ...

  7. UNet语义分割实战:使用UNet实现对人物的抠图

    摘要 在上一篇文章,我总结了一些UNet的基础知识,对UNet不了解的可以看看,文章链接:https://wanghao.blog.csdn.net/article/details/123714994 ...

  8. 图像语义分割实战:TensorFlow Deeplabv3+ 训练自己数据集

    文章目录 前言 一.环境配置 二.训练过程 1.引入库 2.数据集准备 转换为 VOC 格式的数据集 Convert to 灰度图 Convert to tfrecord 3.训练前代码准备 4.主要 ...

  9. 【天池赛事】零基础入门语义分割-地表建筑物识别

    https://tianchi.aliyun.com/competition/entrance/531872/introduction [天池赛事]零基础入门语义分割-地表建筑物识别:第一章 赛题及b ...

  10. 全卷积神经网络( FCN ):语义分割深度模型先驱

    语义分割 简单地说,分割就是抠图.语义分割,就是按图像中物体表达的含义进行抠图. 现在ps已经集成很多自动分割的功能,相比旧版本软件,新软件提高了美工人员的抠图和美图的效率. 如果我们能在更复杂的环境 ...

最新文章

  1. 1 图片channels_深度学习中各种图像库的图片读取方式
  2. LC124 Binary Tree Maximum Path Sum
  3. atlas单机模式代码_生存游戏竞争太大怎么办?在海盗游戏《ATLAS》也可佛系生存...
  4. android 仿360浮动,Android--模仿360底部导航按钮
  5. deLPHI书籍名称
  6. Delphi多媒体设计之TMediaPlayer组件(二)
  7. JDBC(Java语言连接数据库)
  8. Leetcode每日一题:62.unique-paths(不同路径)
  9. coreldraw水涟漪怎么做_不懂怎么挑选水处理设备?跟贝斯沃了解这3点再做决定,轻松挑出适合自己的...
  10. thinkphp——登录界面
  11. 解压文件win10自动删除
  12. sigmoid 激励函数
  13. 作用JavaScript访问和操作数据库
  14. 中国石油大学《画法几何》在线考试
  15. 写在《大国崛起》之后,“中国崛起”之前(二)
  16. 小项目正确的操作姿势,碾压工薪阶层
  17. HTML中的音视频标签
  18. 电子设计大赛-电源电路
  19. [转载]打工辛酸路:我是一朵飘零的花之61
  20. 计算机类课程嵌入式系统的特点及其应用,嵌入式系统的准确定义、特点及其重要性...

热门文章

  1. python ftp timeout_Python ftp client 处理含有中文的文件名详解
  2. iphone电池怎么保养_手机电池不耐用怎么办啊?平时要怎么保养呢?我来告诉你...
  3. python生成器的实现及原理
  4. faster rcnn第二阶段loss出现nan_深度学习训练Loss异常Debug思路
  5. springmvc配置中文乱码过滤器
  6. 类似纪念碑谷的unity2d素材包_《纪念碑谷》:引领小清新风格的2.5D插画风游戏...
  7. Javascript:利用JS在空白网页中绘制简单图形
  8. SLAM_SLAM中一般是如何求解相机的运动的?
  9. Facebook最新研究:全局一致的视频深度估计
  10. 论文评析-Incremental Boosting Convolutional Neural Network for Facial Action Unit Recognition,NIPS, 2016