点击上方“小白学视觉”,选择加"星标"或“置顶

重磅干货,第一时间送达

分割对于图像解释任务至关重要,那就不要落后于流行趋势,让我们来实施它,我们很快就会成为专业人士!

什么是语义分割?

它描述了将图像的每个像素与类别标签(例如花、人、道路、天空、海洋或汽车)相关联的过程,即我们要输入图像,然后为该图像中的每个像素输出一个类别决策。例如下面这个输入图像,这是一只坐在床上的狗:

因此,在输出中,我们希望为每个像素定义一组类别,即狗、床、后面的桌子和橱柜。在语义分割之后,图像看起来像这样:

关于语义分割的一件有趣的事情是它不区分实例,即如果此图像中有两只狗,它们将仅被描述为一个标签,即 dog ,而不是 dog1 和 dog2。

语义分割一般用于:

  • 自动驾驶

  • 工业检验

  • 卫星图像中值得注意的区域分类

  • 医学影像监查

语义分割实现:

  • 第一种方法是滑动窗口,我们将输入图像分解成许多小的局部图像,但是这种方法在计算上会很昂贵。所以,我们在实践中并没有真正使用这个方法。

  • 另一种方法是完全卷积网络,其中网络有一整堆卷积层,没有完全连接的层,从而保留了输入的空间大小,这在计算上也是极其昂贵的。

  • 第三个也是最好的一个方法,那就是对图像进行上采样和下采样。因此,我们不需要对图像的完整空间分辨率进行所有卷积,我们可能会在原始分辨率下遍历少量卷积层,然后对该特征图进行下采样,然后对其进行上采样。

    在这里,我们只想在网络的后半部分提高我们预测的空间分辨率,以便我们的输出图像现在可以与我们的输入图像具有相同的维度。它的计算效率要高得多,因为我们可以使网络非常深,并以更便宜的空间分辨率运行。

让我们在代码中实现这一点:

  • 导入处理所需的必要库
    Pytorch 的重要功能,例如数据加载器、变量、转换和优化器相关函数。

    导入 VOC12 和 cityscapes 的数据集类,从 transform.py 文件导入 Relabel、ToLabel 和 Colorize 类,从 iouEval.py 文件中导入 iouEval 类。

#SSCV IIITH 2K19
import random
import time
import numpy as np
import torch
print(torch.__version__)
import math
from PIL import Image, ImageOps
from torch.optim import SGD, Adam, lr_scheduler
from torch.autograd import Variable
from torch.utils.data import DataLoader
from torchvision.transforms import  Resize
from torchvision.transforms import ToTensor, ToPILImage
from dataset import cityscapes
from dataset import idd_lite
import sys
print(sys.executable)
from transform import Relabel, ToLabel, Colorize
import matplotlib
from matplotlib import pyplot as plt
%matplotlib inline
import importlib
from iouEval import iouEval, getColorEntry #importing iouEval class from the iouEval.py file
from shutil import copyfile
  • 定义几个全局参数:

NUM_CHANNELS = 3 #RGB Images
NUM_CLASSES = 8 #IDD Lite has 8 labels or Level1 hierarchy of labels
USE_CUDA = torch.cuda.is_available()
IMAGE_HEIGHT = 160
DATA_ROOT = ‘/tmp/school/6-segmentation/user/1/6-segmentation/idd1_lite’
BATCH_SIZE = 2
NUM_WORKERS = 4
NUM_EPOCHS = 100
ENCODER_ONLY = True
device = torch.device(“cuda” )
#device = ‘cuda’
color_transform = Colorize(NUM_CLASSES)
image_transform = ToPILImage()
IOUTRAIN = False
IOUVAL = True
  • 增强,即对图像和目标执行随机增强的不同功能:

class MyCoTransform(object):def __init__(self, enc, augment=True, height=160):self.enc=encself.augment = augmentself.height = heightpassdef __call__(self, input, target):# Resizing data to required sizeinput = Resize((self.height,320), Image.BILINEAR)(input)target = Resize((self.height,320), Image.NEAREST)(target)
if(self.augment):# Random horizontal fliphflip = random.random()if (hflip < 0.5):input = input.transpose(Image.FLIP_LEFT_RIGHT)target = target.transpose(Image.FLIP_LEFT_RIGHT)#Random translation 0–2 pixels (fill rest with padding)transX = random.randint(0, 2) transY = random.randint(0, 2)
input = ImageOps.expand(input, border=(transX,transY,0,0), fill=0)target = ImageOps.expand(target, border=(transX,transY,0,0), fill=7) #pad label filling with 7input = input.crop((0, 0, input.size[0]-transX, input.size[1]-transY))target = target.crop((0, 0, target.size[0]-transX, target.size[1]-transY))
input = ToTensor()(input)target = ToLabel()(target)target = Relabel(255,7)(target)return input, target
  • 加载数据我们将遵循 pytorch 推荐的语义,并使用数据加载器加载数据。

best_acc = 0
co_transform = MyCoTransform(ENCODER_ONLY, augment=True, height=IMAGE_HEIGHT)
co_transform_val = MyCoTransform(ENCODER_ONLY, augment=False, height=IMAGE_HEIGHT)
#train data
dataset_train = idd_lite(DATA_ROOT, co_transform, ‘train’)
print(len(dataset_train))
#test data
dataset_val = idd_lite(DATA_ROOT, co_transform_val, ‘val’)
print(len(dataset_val))
loader_train = DataLoader(dataset_train, num_workers=NUM_WORKERS, batch_size=BATCH_SIZE, shuffle=True)
loader_val = DataLoader(dataset_val, num_workers=NUM_WORKERS, batch_size=BATCH_SIZE, shuffle=False)
  • 既然是分类问题,我们就使用交叉熵损失,但为什么呢?

答案是负对数,在较小值的时候效果不好,并且在较大值的时候效果也不好。因为我们将损失函数加到所有正确的类别上,实际发生的情况是,每当网络为正确的类别,分配高置信度时,损失就低,但是当网络为正确的类别时分配低置信度,损失就高。

criterion = torch.nn.CrossEntropyLoss()
  • 现在让我们加载模型并优化它!

model_file = importlib.import_module(‘erfnet’)
model = model_file.Net(NUM_CLASSES).to(device)
optimizer = Adam(model.parameters(), 5e-4, (0.9, 0.999), eps=1e-08, weight_decay=1e-4)
start_epoch = 1
  • 所以,编码的最终本质就是训练!

import os
steps_loss = 50
my_start_time = time.time()
for epoch in range(start_epoch, NUM_EPOCHS+1):print(“ — — — TRAINING — EPOCH”, epoch, “ — — -”)
epoch_loss = []time_train = []
doIouTrain = IOUTRAIN doIouVal = IOUVAL
if (doIouTrain):iouEvalTrain = iouEval(NUM_CLASSES)
model.train()for step, (images, labels) in enumerate(loader_train):
start_time = time.time()inputs = images.to(device)targets = labels.to(device)outputs = model(inputs, only_encode=ENCODER_ONLY)
# zero the parameter gradientsoptimizer.zero_grad()# forward + backward + optimizeloss = criterion(outputs, targets[:, 0])loss.backward()optimizer.step()
epoch_loss.append(loss.item())time_train.append(time.time() — start_time)
if (doIouTrain):#start_time_iou = time.time()iouEvalTrain.addBatch(outputs.max(1)[1].unsqueeze(1).data, targets.data)#print (“Time to add confusion matrix: “, time.time() — start_time_iou)
# print statisticsif steps_loss > 0 and step % steps_loss == 0:average = sum(epoch_loss) / len(epoch_loss)print(‘loss: {average:0.4} (epoch: {epoch}, step: {step})’, “// Avg time/img: %.4f s” % (sum(time_train) / len(time_train) / BATCH_SIZE))
average_epoch_loss_train = sum(epoch_loss) / len(epoch_loss)
iouTrain = 0if (doIouTrain):iouTrain, iou_classes = iouEvalTrain.getIoU()iouStr = getColorEntry(iouTrain)+’{:0.2f}’.format(iouTrain*100) + ‘\033[0m’print (“EPOCH IoU on TRAIN set: “, iouStr, “%”)
my_end_time = time.time()
print(my_end_time — my_start_time)

在训练了 100 个 epoch 之后,我们会看到:

  • 验证:

#Validate on val images after each epoch of training
print(“ — — — VALIDATING — EPOCH”, epoch, “ — — -”)
model.eval()
epoch_loss_val = []
time_val = []
if (doIouVal):iouEvalVal = iouEval(NUM_CLASSES)
for step, (images, labels) in enumerate(loader_val):start_time = time.time()
inputs = images.to(device) targets = labels.to(device)with torch.no_grad():outputs = model(inputs, only_encode=ENCODER_ONLY) #outputs = model(inputs)loss = criterion(outputs, targets[:, 0])epoch_loss_val.append(loss.item())time_val.append(time.time() — start_time)
#Add batch to calculate TP, FP and FN for iou estimationif (doIouVal):#start_time_iou = time.time()iouEvalVal.addBatch(outputs.max(1)[1].unsqueeze(1).data, targets.data)#print (“Time to add confusion matrix: “, time.time() — start_time_iou)if steps_loss > 0 and step % steps_loss == 0:average = sum(epoch_loss_val) / len(epoch_loss_val)print(‘VAL loss: {average:0.4} (epoch: {epoch}, step: {step})’, “// Avg time/img: %.4f s” % (sum(time_val) / len(time_val) / BATCH_SIZE))
average_epoch_loss_val = sum(epoch_loss_val) / len(epoch_loss_val)
iouVal = 0
if (doIouVal):
iouVal, iou_classes = iouEvalVal.getIoU()print(iou_classes)iouStr = getColorEntry(iouVal)+’{:0.2f}’.format(iouVal*100) + ‘\033[0m’print (“EPOCH IoU on VAL set: “, iouStr, “%”)

  • 可视化输出:

# Qualitative Analysis
dataiter = iter(loader_val)
images, labels = dataiter.next()
if USE_CUDA:images = images.to(device)
inputs = images.to(device)
with torch.no_grad():outputs = model(inputs, only_encode=ENCODER_ONLY)
label = outputs[0].max(0)[1].byte().cpu().data
label_color = Colorize()(label.unsqueeze(0))
label_save = ToPILImage()(label_color)
plt.figure()
plt.imshow(ToPILImage()(images[0].cpu()))
plt.figure()
plt.imshow(label_save)

输出图像

很快我们就可以准备好我们的模型了!

随意使用我们新设计的模型,尝试增加更多的 epoch 并观察我们的模型表现得更好!

因此,简而言之,现在我们将能够轻松地将图像的每个像素与类标签相关联,并可以调整超参数以查看显示的更改。本文展示了语义分割的基础知识,要对实例进行分类,我们需要进行实例分割,这是语义分割的高级版本。

下载1:OpenCV-Contrib扩展模块中文版教程

在「小白学视觉」公众号后台回复:扩展模块中文教程即可下载全网第一份OpenCV扩展模块教程中文版,涵盖扩展模块安装、SFM算法、立体视觉、目标跟踪、生物视觉、超分辨率处理等二十多章内容。

下载2:Python视觉实战项目52讲

在「小白学视觉」公众号后台回复:Python视觉实战项目即可下载包括图像分割、口罩检测、车道线检测、车辆计数、添加眼线、车牌识别、字符识别、情绪检测、文本内容提取、面部识别等31个视觉实战项目,助力快速学校计算机视觉。

下载3:OpenCV实战项目20讲

在「小白学视觉」公众号后台回复:OpenCV实战项目20讲即可下载含有20个基于OpenCV实现20个实战项目,实现OpenCV学习进阶。

交流群

欢迎加入公众号读者群一起和同行交流,目前有SLAM、三维视觉、传感器、自动驾驶、计算摄影、检测、分割、识别、医学影像、GAN、算法竞赛等微信群(以后会逐渐细分),请扫描下面微信号加群,备注:”昵称+学校/公司+研究方向“,例如:”张三 + 上海交大 + 视觉SLAM“。请按照格式备注,否则不予通过。添加成功后会根据研究方向邀请进入相关微信群。请勿在群内发送广告,否则会请出群,谢谢理解~

语义分割:最简单的代码实现!相关推荐

  1. CV之IS:利用pixellib库基于deeplabv3_xception模型对《庆余年》片段实现语义分割/图像分割简单代码全实现

    CV之IS:利用pixellib库基于deeplabv3_xception模型对<庆余年>片段实现语义分割/图像分割简单代码全实现 目录 利用pixellib库基于deeplabv3_xc ...

  2. 语义分割数据增强python代码

                                                           语义分割数据增强python-pytorch代码-语义分割github项目 0. 先放gi ...

  3. 基于迁移学习的语义分割算法分享与代码复现

    摘要:语义分割的数据集是比较大的,因此训练的时候需要非常强大的硬件支持. 本文分享自华为云社区<[云驻共创]基于迁移学习的语义分割算法分享>,原文作者:启明. 此篇文章是分享两篇基于迁移学 ...

  4. 图像语义分割快速入门--keras代码示例-----基于tensorflow2.x-----看完就会系列!!!!

    语义分割tensorflow2.x以上版本实现!!! 整篇文章基于tensorflow2.x版本自带的keras编写代码 依赖库 分割数据集 读取数据 主函数中需要调用的部分子函数 主函数 模型 最后 ...

  5. 【语义分割系列】ICNET(实时语义分割)理论以及代码实现

    git地址:https://github.com/Tramac/awesome-semantic-segmentation-pytorch 包括: FCN ENet PSPNet ICNet Deep ...

  6. CNN for Semantic Segmentation(语义分割,论文,代码,数据集,标注工具,blog)

    在FCN网络在2104年提出后,越来越多的关于图像分割的深度学习网络被提出,相比传统方法,这些网络效果更好,运算速度更快,已经能成熟的运用在自然图像上.语义分割显然已经是计算机视觉领域的一个热门研究领 ...

  7. 语义分割代码实现流程

    语义分割的整体实现代码大致思路很简单,但是具体到细节,就有很多可说的东西. 之前写过一篇文章,可能有些地方现在又有了新的思路或者感受,或者说之前没有突出重点. 作为一个小白,这里把自己知道的知识写一下 ...

  8. 图像语义分割之FCN和CRF

    https://blog.csdn.net/u012759136/article/details/52434826?locationNum=7&fps=1 前言 (呕血制作啊!)前几天刚好做了 ...

  9. 关于图像语义分割的总结和感悟

    还是在继续找pooling,unpooling,upsampling的路上发现好文章 转自:https://www.2cto.com/kf/201609/545237.html 前言 (呕血制作啊!) ...

  10. 深度学习语义分割理论与实战指南

    本文来自微信公众号[机器学习实验室] 深度学习语义分割理论与实战指南 1 语义分割概述 2 关键技术组件 2.1 编码器与分类网络 2.2 解码器与上采样 2.2.1 双线性插值(Bilinear I ...

最新文章

  1. python的HTML文件中使用和加载CSS文件
  2. endnote一打开就自动关闭_word mac版如何彻底删除endnote插件?mac版word移除endnote加载项的方法...
  3. 单片机与gsm通信c语言,gsm模块如何与单片机通信?
  4. oracle 邻接模型,【原创】MySQL 模拟Oracle邻接模型树形处理
  5. js 根据时间生成唯一订单号
  6. linux sed 1的意思,linux命令(1):sed命令
  7. 专业的优化服务,就是为你争取时间!
  8. PC-如何禁用 Cookie
  9. java模拟多个用户操作,JAVA 模拟多用户提交动作
  10. 大数据分析平台具有哪些价值
  11. 一起谈谈 Java 9 的新特性
  12. Delphi 与 DirectX 之 DelphiX(63): TDIB.DoPosterize();
  13. 原生JavaScript实现异步校验详解
  14. [leetcode]72. Edit Distance 最少编辑步数
  15. SpringBoot 实现SQL脚本自动执行
  16. 双11,立减¥3554!戴尔官网撩客服砍价带走高性能电脑,速来!
  17. 网络正常,QQ无法登录,一直显示登录中
  18. android rxbus github,RxBus for Android
  19. 【数论】Pollard-Rho 算法总结
  20. linux动态频率调节系统cpufreq,Linux的cpufreq(动态变频)技术

热门文章

  1. 一个可以卷起来的蓝牙键盘,简直是办公码字神器!
  2. Github免费中文书《Go入门指南》,带你从零学Go | 极客头条
  3. 百度SLG拿下前锤子科技CTO钱晨,还要合并小鱼在家? | 极客头条
  4. AI黑科技:呵护地球,我们是认真的
  5. 免费公开课 | 数据科学家,从入门到精进!【今晚福利】
  6. Java 常用代码汇总
  7. 23 种设计模式的通俗解释
  8. Spring Boot + Vue 如此强大?竟然可以开发基于 C/S 架构的应用
  9. 一次SQL查询优化原理分析(900W+数据,从17s到300ms)
  10. SpringBoot实现过滤器、拦截器与切片