在MATLAB环境下使用深度学习网络DeepLabV3+进行语义分割(云图分割)

摘要:本文主要讲述在MATLAB2020a环境下利用深度神经网络DeepLabV3+进行语义分割,分割感图像中的云层。讲述了:1.训练数据的获取、训练集制作;2.DeepLabV3+模型的构建;3.DeepLabV3+模型训练和验证

1.数据获取与训练集制备

为了方便大家,这里我把我构建完的的数据集放到云盘上(提取码:wtx4):

如果感兴趣数据集是如何建立的,请参考如下部分,否则可以直接跳转至 3)制作神经网络的输入数据

气象卫星遥感图像数据来源与日本的葵花8产品,相应的数据介绍链接

数据获取可直接跳转本链接:

调整至合适的分辨率(图1)然后右键另存为图像(图2)

                                图1 网页截图

                             图2 下载云图                                                                                                                    

我裁剪的尺寸大概是纬度5个格子(太懒了没换算一个格子是几度)。这样就得到了用于训练的原始数据。

有了原始数据后,还需要相应的标签才能构建完整训练数据集。一般处理图像类的卷积神经网络输入都是图像,而标签(或言之输出结果)是根据任务而定的。以分类任务为例,标签就是一个单一类别,以目标检测为例,输出是4维向量(4个元素分别代表矩形框左上角x坐标,左上角y坐标,矩形框x方向长度,y方向长度)。而语义分割的输出是什么呢?语义分割的本质是对图像中每一个像素进行分类,对图像中每个像素都打上一个标签就是语义分割的标注过程。一般情况下,这个工作需要我们手工完成且工作量极大(在下一篇文章中会讲述用MATLAB的标注工具箱进行完整标注的过程),但本文选取的云图分割由标注好的标签。

如下图(图3)左下角产品类型选中CloudType云类,右上角选项选择Blank Map白板,再右键保存得到(图4)

                                图3 网页截图(标签)

                                图4 下载云类别(标签)

至此,图4即为图2的标签数据。在地图上截取不同区域或者换不同时间点下的图像,采集了69组原始图像和原始标签。

结合图3和图4可以看到,标注的云类有9种

云类别

数据结果赋值

图像结果颜色信息

雨层云Ns

6

(204   204   0)

层云St

9

(255    0    0)

积云Cu

7

(255   153   153)

卷云Ci

1

(204   204  255)

深对流云Dc

3

(0    0    255)

其他(两种方式二选一)

卷层云Cs:2

高积云Ac:4

高层云As:5

层积云Sc:8

背景:0

(102   102  255)

(255   255  204)

(255   255    0)

(255   102    51)

(0   0  0)

本文不需要对云类分割的这么详细,只需要将九类云都分割为云这一类就行

云类别

数据结果赋值

图像结果颜色信息

1

(204   204   0)

(255    0    0)

(255   153   153)

(204 204 255)

(0     0     255)

(102   102  255)

(255   255  204)

(255   255    0)

(255   102    51)

背景

0

(0   0  0)

 

 

1)首先裁剪原始数据:

将相应的图像和标签对应上,这里我将第一张原图命名为canvas1.png,第一个标签命名为canvas1-seg.png。由于图像和标签的分辨率都是1464*908,基本上可以划分为6个小块:(在原图和标签图的文件夹下运行如下代码)

%% 裁剪69副图像
for n=1:69
I=imread(['canvas',num2str(n),'.png']);

I1=imcrop(I,[0,0,488,454]);
I2=imcrop(I,[489,0,487,454]);
I3=imcrop(I,[977,0,488,454]);
I4=imcrop(I,[0,455,488,454]);
I5=imcrop(I,[489,455,487,454]);
I6=imcrop(I,[977,455,488,454]);

Img={I1 I2 I3 I4 I5 I6};
for i=1:6
Img2=Img(i);
Img3=Img2{1,1};
% Img3=imresize(Img3,[454 488]);
% imwrite(Img2{1,1},[num2str(n),'seg-',num2str(i),'.jpg']);
imwrite(Img3,[num2str(n),'-',num2str(i),'.jpg']);
end
end

将生成的图像放入Canvas-Img文件夹

2)之后对原始标签数据进行操作:

%% ImgSegCrop
for n=1:69
I=imread(['canvas',num2str(n),'-seg.png']);
I1=imcrop(I,[0,0,488,454]);
I2=imcrop(I,[488,0,487,454]);
I3=imcrop(I,[977,0,488,454]);
I4=imcrop(I,[0,455,488,454]);
I5=imcrop(I,[489,455,487,454]);
I6=imcrop(I,[977,455,488,454]);
Img={I1 I2 I3 I4 I5 I6};
%% 划分云层和背景
for k=1:6
    Ik=Img(k);
    Ik=Ik{1,1};
%     Ik=imresize(Ik,[454 488]);
Itmp=Ik(:,:,1);
WIDTH=size(Ik);
for i=1:WIDTH(1)
    for j=1:WIDTH(2)
        if Ik(i,j,1)==0&&Ik(i,j,2)==0&&Ik(i,j,3)==0 %三通道均为0的是背景
            Itmp(i,j)=0;
        else
            Itmp(i,j)=1;             %否则是云层
        end
     end
end
imwrite(Itmp,[num2str(n),'-',num2str(k),'.png'])
end
end

将生成的png标签拷贝到Canvas-Label-2中:

这里的图片全是黑的,是因为图像中只有两个值0和1,在uint8下基本上就都是黑色的了。但是颜色灰度不重要,这里的0,1只是类别标签,分别代表背景和云层。

3)制作神经网络的输入数据

制备完训练图像和训练标签后,需要将二者作为MATLAB环境下DeepLabV3+可读取的数据类型,

%% Semantic Segmentation for Cloud
dataFolder = fullfile('.\卫星云图0826\卫星云图0826\葵花8\');%这里填写自己数据所在路径
imageFolderTrain = fullfile(dataFolder,'Canvas-Img');%训练图像路径
labelFolderTrain = fullfile(dataFolder,'Canvas-Label-2');%训练标签路径

imdsTrain = imageDatastore(imageFolderTrain);% 加载训练图像

classNames = ["Back" "Cloud"];%设置类别名称
labelIDs = [0 1];%设置类别相应的编号,就是Canvas-Label-2中几乎全黑的png中的值
pxds = pixelLabelDatastore(labelFolderTrain,classNames,labelIDs);%生成相应的类别标签

之后随便挑一张图检验一下:

% Read image and pixel label data.
A = readimage(imdsTrain,5);%选中第5号图片
C = readimage(pxds,5);%选中第5号标签

% Display the label categories in C
% categories(C{1})
cmap = ColorMap;
% Overlay pixel label data on the image and display.
B = labeloverlay(A, C,'ColorMap',cmap,'Transparency',0.6);
figure
imshow(B)

得到下图,对比原图看到,浅蓝色为云层,蓝紫色为背景

这里的函数ColorMap需要自己写一下:

function cmap = ColorMap()

    cmap = [
    000 000 000   % Back
    102 102 255   % Cloud
           ];

% Normalize between [0 1].
cmap = cmap ./ 255;
end

 

2.DeepLabV3+模型的构建

接下来就开始模型的构建了,直接上代码:

%% 数据分析
% 
tbl = countEachLabel(pxds);

frequency = tbl.PixelCount/sum(tbl.PixelCount);
bar(1:numel(classNames),frequency)
xticks(1:numel(classNames)) 
xticklabels(tbl.Name)
xtickangle(45)
ylabel('Frequency') %这里计算云层像素总个数和背景像素总个数之比,用于更改输出层的权重,如果背景元素数量远多于代分割的目标时,不改权重会大大降低网络性能

%% 制作语义分割网络DeeplabV3+
% 定义网络输入大小,与图像大小相等.
imageSize = [454 488 3];

% 定义类别数量.
numClasses = numel(classNames);

%构建deeplabV3+.
lgraph = deeplabv3plusLayers(imageSize, numClasses, "mobilenetv2");%这里骨干网络(图像特征提取网络)选取mobilenetv2,该网络带有ImageNet训练过的参数,采用迁移学习方法可大大提升训练效率

% 设置类别权重
imageFreq = tbl.PixelCount ./ tbl.ImagePixelCount;
classWeights = median(imageFreq) ./ imageFreq
% 修改输出层
pxLayer = pixelClassificationLayer('Name','labels','Classes',tbl.Name,'ClassWeights',classWeights);
lgraph = replaceLayer(lgraph,"classification",pxLayer);

3.DeepLabV3+模型训练和验证

完成网络搭建后,就可以设置超参数、进行数据增强并开始训练了

%% 设置训练参数
options = trainingOptions('adam', ...%选取adam优化器
    'LearnRateSchedule','piecewise',...
    'LearnRateDropPeriod',20,...%学习率每20代降低一次
    'LearnRateDropFactor',0.4,...%学习率每20代降低0.4
    'InitialLearnRate',1e-4, ...%初始学习率
    'L2Regularization',0.005, ...
    'MaxEpochs',50, ...  %最大迭代次数
    'MiniBatchSize',8, ...%小批量尺寸,可根据显存更改,这里用的8g显存
    'Shuffle','every-epoch', ...
    'VerboseFrequency',2,...
    'Plots','training-progress');%绘制训练曲线
% 图像增强,
augmenter = imageDataAugmenter('RandXReflection',true,...
    'RandXTranslation',[-10 10],'RandYTranslation',[-10 10]);%进行平移和翻转
pximds = pixelLabelImageDatastore(imdsTrain,pxds, ...
    'DataAugmentation',augmenter);
% 训练网络
[net, info] = trainNetwork(pximds,lgraph,options);

这里在执行lgraph = deeplabv3plusLayers(imageSize, numClasses, "mobilenetv2");时如果没有安装mobilenetv2,则会运行报错,参考我这篇文章中的解决方式

这样就开始模型的训练了,训练过程如下图

可以看到近4小时训练后最终网络在训练集上的准确率有近85%,不算特别高。先看一下训练集上的训练效果:

%% 动态显示
imagePath=pwd;
imageFiles = dir(imagePath); %%读取目录文件下的所有图片文件  
numFiles = length(imageFiles);%%获取图片的数量 
figure()
for i = 3:numFiles
    j = i-2; 
    subplot(1,2,1)
    imageFile = strcat(imagePath,'\',imageFiles(i).name);
    I = imread(imageFile);
    imshow(I,[],'parent',gca)
    subplot(1,2,2)
    C = semanticseg(I, net);
    B = labeloverlay(I,C,'Colormap',cmap,'Transparency',0.4);
    imshow(B,[],'parent',gca)
%     pixelLabelColorbar(cmap, classes);
    pause(2)
end

训练时可以将414张图像拆分整训练和验证集,这样验证部分可以放在验证集上进行。由于云层类型较多,有些云层十分稀薄,确实不太好界定,因此能够达到这样的训练效果应该还算可以了。

重新再网上下了几张图,构成测试集:

测试结果如下,效果差不多:

小结:本文主要讲述了再MATLAB环境下使用DeepLabV3+实现云层分割。介绍了数据集构建、模型构建和训练以及效果验证。训练集上实现了85%的准确率。但缺少了完整的数据人工标注过程。后续会继续出一篇包含数据标注的完整语义分割任务Demo。

 

欢迎交流和指正:企鹅2501896344

 

 

 

  • 8
    点赞
  • 101
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 23
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 23
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Le0virg0

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值