使用PyTorch进行语义分割「建议收藏」

使用PyTorch进行语义分割「建议收藏」本篇文章使用进行pytorch进行语义分割的实验。1.什么是语义分割?语义分割是一项图像分析任务,我们将图像中的每个像素分类为对应的类。这类似于我们人类在默认情况下一直在做的事情。每当我们看到某些画面时,我们都会尝试“分割”图像的哪一部分属于哪个类/标签/类别。从本质上讲,语义分割是我们可以在计算机中实现这一点的技术。您可以在我们关于图像分割的帖子中阅读更多关于分割的内容。这篇文章…

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE使用 1年只要46元 售后保障 童叟无欺

本篇文章使用进行pytorch进行语义分割的实验。

1.什么是语义分割?

语义分割是一项图像分析任务,我们将图像中的每个像素分类为对应的类。 这类似于我们人类在默认情况下一直在做的事情。每当我们看到某些画面时,我们都会尝试“分割”图像的哪一部分属于哪个类/标签/类别。 从本质上讲,语义分割是我们可以在计算机中实现这一点的技术。 您可以在我们关于图像分割的帖子中阅读更多关于分割的内容。 这篇文章的重点是语义分割 ,所以,假设我们有下面的图像。

使用PyTorch进行语义分割「建议收藏」

经过语义分割,会得到如下输出:

使用PyTorch进行语义分割「建议收藏」

如您所见,图像中的每个像素都被分类为各自的类。例如,人是一个类,自行车是另一个类,第三个是背景。 简单说,这就是语义分割。

2.语义分割的应用

语义分割最常见的用例是:

2.1 自动驾驶

在自主驾驶中,计算机驾驶汽车需要对前面的道路场景有很好的理解。分割出汽车、行人、车道和交通标志等物体是很重要的。

使用PyTorch进行语义分割「建议收藏」

2.2 人脸分割

面部分割用于将面部的每个部分分割成语义相似的区域-嘴唇、眼睛等。这在许多现实世界的应用程序中都是有用的。一个非常有趣的应用程序可以是虚拟美颜。

使用PyTorch进行语义分割「建议收藏」

2.3 室内物体分割

你能猜出这个在哪里使用吗?在AR(增强现实)和VR(虚拟现实)中。应用程序可以分割整个室内区域,以了解椅子、桌子、人、墙和其他类似物体的位置,从而可以高效地放置和操作虚拟物体。

使用PyTorch进行语义分割「建议收藏」

2.4  大地遥感

地球遥感是一种将卫星图像中的每个像素分类为一个类别的方法,以便我们可以跟踪每个区域的土地覆盖情况。因此,如果在某些地区发生了严重的森林砍伐,那么就可以采取适当的措施。在卫星图像上使用语义分割可以有更多的应用。

使用PyTorch进行语义分割「建议收藏」

让我们看看如何使用PyTorch和Torchvision进行语义分割。

3 torchvision的语义分割

我们将研究两个基于深度学习的语义分割模型。全卷积网络(FCN)和DeepLabv3。这些模型已经在COCO Train 2017数据集的子集上进行了训练,该子集对应于PASCALVOC数据集。模型共支持20个类别。

3.1.输入和输出

在我们开始之前,让我们了解模型的输入和输出。 这些模型期望输入一个3通道图像(RGB),它使用Imagenet的均值和标准差归一化,即, 平均值=[0.485,0.456,0.406],标准差=[0.229,0.224,0.225] 。

输入维数为[Ni x Ci x Hi x Wi] ,其中,

Ni ->批次大小

Ci ->通道数(即3)

Hi ->图片的高度

Wi ->图像的宽度

而模型的输出维数为[No x Co x Ho x Wo] ,其中

No ->批次大小(与Ni相同)

Co->是数据集的类数!

Ho ->图像的高度(几乎在所有情况下都与Hi相同)

Wo ->图像的宽度(几乎在所有情况下都与Wi相同)

注:torchvision模型的输出是一个有序的字典,而不是一个torch.Tensor(张量)。 在推理(.val()模式)过程中,输出是一个有序的Dict,且只有一个键-值对,键为out,它的相应值具有[No x Co x Ho x Wo]的形状。 

3.2.具有Resnet-101骨干的FCN 全卷积网络

FCN是第一次成功的使用神经网络用于语义分割工作。让我们看看如何在Torchvision中使用该模型。

3.2.1 加载模型

from torchvision import models
fcn = models.segmentation.fcn_resnet101(pretrained=True).eval()

很简单!我们有一个基于Resnet101的预先训练的FCN模型。如果模型尚未存在于缓存中,则pretrained=True标志将下载该模型。该.val方法将以推理模式加载它。

3.2.2.加载图像

接下来,让我们加载一个图像!我们直接从URL下载一个鸟的图像并保存它。我们使用PIL加载图像。

在当前目录中,下载一张图片。

wget -nv https://static.independent.co.uk/s3fs-public/thumbnails/image/2018/04/10/19/pinyon-jay-bird.jpg -O bird.png

加载显示图像

from PIL import Image
import matplotlib.pyplot as plt
import torch
 
img = Image.open('./bird.png')
plt.imshow(img); plt.show()

使用PyTorch进行语义分割「建议收藏」

3.2.3.对图像进行预处理

为了使图像达到输入格式要求,以便使用模型进行推理,我们需要对其进行预处理并对其进行正则化! 因此,对于预处理步骤,我们进行以下操作。

 将图像大小调整为(256×256)

将其转换为(224×224)

将其转换为张量-图像中的所有元素值都将被缩放,以便在[0,1]之间而不是原来的[0,255]范围内。

将其正则化,使用Imagenet数据 的均值=[0.485,0.456,0.406],标准差=[0.229,0.224,0.225]

最后,我们对图像进行增加维度,使它从[C x H x W]变成[1x C x H x W]。这是必需的,因为模型需要按批处理图像。

# Apply the transformations needed
import torchvision.transforms as T
trf = T.Compose([T.Resize(256),
                 T.CenterCrop(224),
                 T.ToTensor(), 
                 T.Normalize(mean = [0.485, 0.456, 0.406], 
                             std = [0.229, 0.224, 0.225])])
inp = trf(img).unsqueeze(0)

让我们看看上面的代码单元是做什么的。 torchvision有许多有用的函数。其中之一是用于预处理图像的Transforms。T.Compose是一个函数,它接受一个列表,其中每个元素都是transforms 类型,它返回一个对象,我们可以通过这个对象传递一批图像,所有所需的转换都将应用于图像。

让我们来看看应用于图像上的转换:

T.Resize(256):将图像尺寸调整为256×256

T.CenterCrop(224):从图像的中心抠图,大小为224×224

T.ToTensor():将图像转换为张量,并将值缩放到[0,1]范围

T.Normalize(mean, std):用给定的均值和标准差对图像进行正则化。

3.2.4.正向传递通过网络

现在我们已经对图像进行了所有的预处理,让我们通过模型并得到OUT键。 正如我们前面提到的,模型的输出是一个有序的Dict,所以我们需要从其中取出out键的value来获得模型的输出。

# Pass the input through the net
out = fcn(inp)['out']
print (out.shape)

输出为:

torch.Size([1, 21, 224, 224])

所以,out是模型的最终输出。正如我们所看到的,它的形状是[1 x 21 x H x W],正如前面所讨论的。因为,模型是在21个类上训练的,输出有21个通道!(包括背景类) 现在我们需要做的是,使这21个通道输出到一个2D图像或一个1通道图像,其中该图像的每个像素对应于一个类! 因此,2D图像(形状[HxW])的每个像素将与相应的类标签对应,对于该2D图像中的每个(x,y)像素将对应于表示类的0-20之间的数字。 我们如何从这个[1 x 21 x H x W]的列表到达那里?我们为每个像素位置取一个最大索引,该索引表示类的下标,看到这里是否似曾相识,对了,之前的文章讲到,多分类的输出是一个列表,存有每个类的置信度,这里每个像素点的21个通道对应着每个类的置信度。

import numpy as np
om = torch.argmax(out.squeeze(), dim=0).detach().cpu().numpy()
print (om.shape)
(224, 224)

out.squeeze()对out进行降纬,变为[21 x H x W],  dim=0说明对第一纬(21)进行取极大值操作,故结果为[H x W]。

print (np.unique(om))
[0 3]

可见,处理完的列表中共有2种元素,0(背景),3(鸟)。正如我们所看到的,现在我们有了一个2D图像,其中每个像素属于一个类。最后一件事是把这个2D图像转换成一个分割图像,每个类标签对应于一个RGB颜色,从而使图像易于观看。

3.2.5.解码输出

我们将使用以下函数将此2D图像转换为RGB图像,其中每个(元素)标签映射到相应的颜色。

# Define the helper function
def decode_segmap(image, nc=21):
   
  label_colors = np.array([(0, 0, 0),  # 0=background
               # 1=aeroplane, 2=bicycle, 3=bird, 4=boat, 5=bottle
               (128, 0, 0), (0, 128, 0), (128, 128, 0), (0, 0, 128), (128, 0, 128),
               # 6=bus, 7=car, 8=cat, 9=chair, 10=cow
               (0, 128, 128), (128, 128, 128), (64, 0, 0), (192, 0, 0), (64, 128, 0),
               # 11=dining table, 12=dog, 13=horse, 14=motorbike, 15=person
               (192, 128, 0), (64, 0, 128), (192, 0, 128), (64, 128, 128), (192, 128, 128),
               # 16=potted plant, 17=sheep, 18=sofa, 19=train, 20=tv/monitor
               (0, 64, 0), (128, 64, 0), (0, 192, 0), (128, 192, 0), (0, 64, 128)])
 
  r = np.zeros_like(image).astype(np.uint8)
  g = np.zeros_like(image).astype(np.uint8)
  b = np.zeros_like(image).astype(np.uint8)
   
  for l in range(0, nc):
    idx = image == l
    r[idx] = label_colors[l, 0]
    g[idx] = label_colors[l, 1]
    b[idx] = label_colors[l, 2]
     
  rgb = np.stack([r, g, b], axis=2)
  return rgb

    idx = image == l
    r[idx] = label_colors[l, 0] 使用了numpy列表的高级索引功能,即使用布尔列表进行索引,在这里就是每个元素赋值成对应标签的颜色。

首先,列表label_colors根据索引存储每个类的颜色。因此,第一类的颜色是背景,存储在label_colors列表的第0个索引处。第二类,即飞机,存储在索引1中,以此类推。 现在,我们必须从我们拥有的2D图像中创建一个RGB图像。因此,我们所做的是为所有3个通道创建空的2D矩阵。 因此,r、g和b是构成最终图像的RGB通道的列表,这些列表中的每一个的形状都是[HxW](这与2D图像的形状相同)。 现在,我们循环存储在label_colors中的每个颜色,并在存在特定类标签的2D图像中获取索引。然后,对于每个通道,我们将其相应的颜色放置到存在该类标签的像素上。 最后,我们将3个独立的通道叠加起来,形成RGB图像。 好吧!现在,让我们使用这个函数来查看最终的输出!

rgb = decode_segmap(om)
plt.imshow(rgb); plt.show()

使用PyTorch进行语义分割「建议收藏」

3.2.6.最终结果

接下来,让我们把所有操作放入一个函数下,并测试更多的图像!

def segment(net, path):
  img = Image.open(path)
  plt.imshow(img); plt.axis('off'); plt.show()
  # Comment the Resize and CenterCrop for better inference results
  trf = T.Compose([T.Resize(256), 
                   T.CenterCrop(224), 
                   T.ToTensor(), 
                   T.Normalize(mean = [0.485, 0.456, 0.406], 
                               std = [0.229, 0.224, 0.225])])
  inp = trf(img).unsqueeze(0)
  out = net(inp)['out']
  om = torch.argmax(out.squeeze(), dim=0).detach().cpu().numpy()
  rgb = decode_segmap(om)
  plt.imshow(rgb); plt.axis('off'); plt.show()

使用PyTorch进行语义分割「建议收藏」

 

使用PyTorch进行语义分割「建议收藏」

使用PyTorch进行语义分割「建议收藏」

使用PyTorch进行语义分割「建议收藏」

 

使用PyTorch进行语义分割「建议收藏」

 

使用PyTorch进行语义分割「建议收藏」

3.4.多个对象

如果我们测试一个更复杂的图像,那么我们可以开始看到一些不同的结果。

wget -nv "https://images.pexels.com/photos/2385051/pexels-photo-2385051.jpeg" -O dog-park.png
img = Image.open('./dog-park.png')
plt.imshow(img); plt.show()
 
print ('Segmenatation Image on FCN')
segment(fcn, path='./dog-park.png', show_orig=False)
 
print ('Segmenatation Image on DeepLabv3')
segment(dlab, path='./dog-park.png', show_orig=False)

使用PyTorch进行语义分割「建议收藏」

 

使用PyTorch进行语义分割「建议收藏」

FCN结果

使用PyTorch进行语义分割「建议收藏」

 DeepLab结果

两者有细微差别

参考连接:https://www.learnopencv.com/pytorch-for-beginners-semantic-segmentation-using-torchvision/

 

 

 

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/171686.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)
blank

相关推荐

  • 《FFmpeg从入门到精通》读书笔记(二)[通俗易懂]

    《FFmpeg从入门到精通》读书笔记(二)[通俗易懂]写在前面2019.06.18第三章知识点(未进行排版)第三章FFmpeg转封装一、MP4格式标准MP4文件由许多个Box与FullBox组成;每个Box由Header和Data两部分组成;FullBox是Box的扩展,其在Box结构的基础上,在Header中增加8位version标志和24为flags标志;Header包含了整个Box的长度的大小(size)和类型(ty…

  • java中的protected的权限范围_java中public private protected

    java中的protected的权限范围_java中public private protected摘要:  对于类的成员而言,其能否被其他类所访问,取决于该成员的修饰词;而对于一个类而言,其能否被其他类所访问,也取决于该类的修饰词。在Java中,类成员访问权限修饰词有四类:private,无(包访问权限),protected和public,而其中只有包访问权限和public才能修饰一个类(内部类除外)。特别地,很多Java书籍对protected可见性的介绍都比较笼统,本文重点说明了p…

    2022年10月25日
  • 语音合成技术_ai语音合成软件免费的

    语音合成技术_ai语音合成软件免费的语音合成技术原理语音合成(texttospeech),简称TTS。将文字转化为语音的一种技术,类似于人类的嘴巴,通过不同的音色说出想表达的内容。将计算机自己产生的、或外部输入的文字信息转变为可以听得懂的、流利的汉语口语输出的技术。TTS的基本组成:(1)文本分析对输入文本进行语言学分析(主要模拟人对自然语言的理解过程),逐句进行词汇的、语法的和语义的分析,以确定句子的低层结构和每个字的音素的组成,包括文本的断句、字词切分、多音字的处理、数字的处理、缩略语的处理等。使计算机对输入的文本能完全理解,

    2022年10月21日
  • asp.net中英文转换

    asp.net中英文转换一、中英文切换主要是依靠资源文件(Resources):资源文件名称格式:"页面名称加后缀.resx"      资源文件分为本地[App_LocalResources]和全球化[App_GlobalResources]二、实现过程:  本地资源:1.添加文件夹[App_LocalResources]                    2.创建以.resx结尾的资源文件   …

    2022年10月24日
  • Android UI设计常用尺寸及基本知识

    Android UI设计常用尺寸及基本知识屏幕尺寸指实际的物理尺寸,为屏幕对角线的测量。为了简单起见,Android把实际屏幕尺寸分为四个广义的大小:小,正常,大,特大。像素(PX)代表屏幕上一个物理的像素点代表屏幕上一个物理的像素点。屏幕密度为解决Android设备碎片化,引入一个概念DP,也就是密度。指在一定尺寸的物理屏幕上显示像素的数量,通常指分辨率。为了简单起见,Android

  • 监控android USB拔插

    监控android USB拔插最近在做项目中遇到一个需要监控USB拔插来关闭服务的问题,当时查了不少资料,都是说android3.0以上的USB类可以监控,╮(╯▽╰)╭比较难搞后来发现其实可以变通的监控外部电源来实现,相当于监控USB了呵呵,记录下来Intent.ACTION_POWER_DISCONNECTED就是它了

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号