之前这篇文章介绍了MATLAB环境构建DeepLabV3+进行云层分割。但数据来源有完整标签,因此少了人工标注过程,在泛化到自己的数据集时可能会遇到障碍。
1.数据集构建
因此在MATLAB中找了自带的数据E:\MATLAB2020b\toolbox\vision\visiondata\stopSignImages (我用的2020b版本)。将这个文件夹中的图片复制出来,在根目录下建一个新的文件夹 E:\stopsignresize 并将图片放入文件夹中。
之后写一个更改图片尺寸的函数:
imagePath = 'E:\stopsignresize\';
imageFiles = dir(imagePath); %%读取目录文件下的所有图片文件
numFiles = length(imageFiles);%%获取图片的数量
parfor i=3:numFiles %%matlab 并行 其实和for一个用法
j = i-2;
disp(j); %%disp() 函数直接将内容输出在Matlab命令窗口中
imageFile = strcat(imagePath,imageFiles(i).name); %%strcat()函数经常出现在批量处理的时候,这个时候我们需要用到for循环,然后这个函数能够让变量和路径产生一些关系,这个时候我们就可以对其进行批量处理。
A = imread(imageFile); %%读入图片
B = imresize(A,[395 700]); %%修改图片尺寸
imwrite(B,imageFile); %%保存图片 。
end
运行这段代码,将原来1630*920的图片改成700*395,否则训练检测器的时候回显示图片太大显存不足。
之后打开MATLAB自带的标注工具,在命令行输入:
或者点这里
打开标注工具:
之后,加载MATLAB视觉工具箱中自带的stopsign图片数据(图片路径:E:\stopsignresize)
得到如下界面:
这次在ROI Labels里选中Pixel label像素标签,并给背景类起名为Back
同理给StopSign类起名:
之后就可以开始标注了,语义分割的标注和目标检测的标注完全不是一个量级的,遇到复杂的样本,单张图像的标注都是以分钟来计算的。接下来咱们开始第一张图像的标注:
记得首先标注背景,再标StopSign(顺序不可颠倒)
背景按照多边形标注,标4个点形成一个矩形,然后拉一下各个顶点充满屏幕再。。。算了直接来动图吧......
都标注好后,导出到工作区(这里注意,是将所有图片标注好后统一输出一个gTruth到工作区):
导出gTruth格式:
确定后会生成gTruth,同时在文件夹里生成PixelLabelData标签:
之后运行:
%% 制作数据集
% 导入图片
imgDir = fullfile('E:\stopsignresize');
imds = imageDatastore(imgDir);
% 显示一张图片
I = readimage(imds,1);
I = histeq(I);
imshow(I)
% 导入并制作像素标签
classes = [
"StopSign"
"Background"
]; %定义类别名称
pxds = pixelLabelDatastore(gTruth);%制作像素类别标签
% 显示其中一张图片并叠加标注信息
C = readimage(pxds,1);
cmap = ColorMap;
B = labeloverlay(I,C,'ColorMap',cmap);
imshow(B)
pixelLabelColorbar(cmap,classes);
function cmap = ColorMap()
% Define the colormap used by CamVid dataset.
cmap = [
255 000 000 % Back
000 000 000 % St
];
% Normalize between [0 1].
cmap = cmap ./ 255;
end
function pixelLabelColorbar(cmap, classNames)
% Add a colorbar to the current axis. The colorbar is formatted
% to display the class names with the color.
colormap(gca,cmap)
% Add colorbar to current figure.
c = colorbar('peer', gca);
% Use class names for tick marks.
c.TickLabels = classNames;
numClasses = size(cmap,1);
% Center tick labels.
c.Ticks = 1/(numClasses*2):1/numClasses:1;
% Remove tick mark.
c.TickLength = 0;
end
看一下我们的标注结果:
之后进行数据分析,查看一下背景像素数量和目标像素数量比:
%% 数据分析
tbl = countEachLabel(pxds);
frequency = tbl.PixelCount/sum(tbl.PixelCount);
bar(1:numel(classes),frequency)
xticks(1:numel(classes))
xticklabels(tbl.Name)
xtickangle(45)
ylabel('Frequency')
很明显,大部分像素是背景,小部分像素是目标,这个比值要留着,后面构建网络的时候,输出层要加上这个权重,否则不利于训练收敛。
2.构建DeepLabV3+
%% 制作语义分割网络DeeplabV3+
% 定义网络输入大小,与图像大小相等.
imageSize = [385 700 3];
% 定义类别数量.
numClasses = numel(classes);
%构建deeplabV3+.
lgraph = deeplabv3plusLayers(imageSize, numClasses, "mobilenetv2");
% lgraph = load('Deep-MbV2.mat');
% lgraph = lgraph.mb53;%mobilenet-512分辨率-3类
% 设置类别权重
imageFreq = tbl.PixelCount ./ tbl.ImagePixelCount;
classWeights = median(imageFreq) ./ imageFreq
% 修改输出层
pxLayer = pixelClassificationLayer('Name','labels','Classes',tbl.Name,'ClassWeights',classWeights);
lgraph = replaceLayer(lgraph,"classification",pxLayer);
3.设置训练参数,训练网络
%% 设置训练参数
options = trainingOptions('adam', ...
'LearnRateSchedule','piecewise',...
'LearnRateDropPeriod',10,...
'LearnRateDropFactor',0.4,...
'InitialLearnRate',1e-4, ...
'L2Regularization',0.005, ...
'MaxEpochs',20, ...
'MiniBatchSize',8, ...
'Shuffle','every-epoch', ...
'VerboseFrequency',2,...
'Plots','training-progress');
% 图像增强,
augmenter = imageDataAugmenter('RandXReflection',true,...
'RandXTranslation',[-10 10],'RandYTranslation',[-10 10]);
pximds = pixelLabelImageDatastore(imds,pxds, ...
'DataAugmentation',augmenter);
% 训练网络
[net, info] = trainNetwork(pximds,lgraph,options);
训练过程如下:
训练集上精度很高
4.模型性能验证
在训练集上的效果展示,路径切换至E://stopsignresize:
%% 动态演示
imagePath=pwd;
imageFiles = dir(imagePath); %%读取目录文件下的所有图片文件
numFiles = length(imageFiles);%%获取图片的数量
for i = 3:numFiles
j = i-2;
subplot(1,2,1)
imageFile = strcat(imagePath,'\',imageFiles(i).name);
I = imread(imageFile);
%I=imresize(I,[395 700]);
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(1)
end
从网上下几个图放在testimg文件夹下验证下泛化能力:
%% 动态演示
imagePath=pwd;
imageFiles = dir(imagePath); %%读取目录文件下的所有图片文件
numFiles = length(imageFiles);%%获取图片的数量
for i = 3:numFiles
j = i-2;
subplot(1,2,1)
imageFile = strcat(imagePath,'\',imageFiles(i).name);
I = imread(imageFile);
I=imresize(I,[395 700]);
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(1)
end
运行结果:
由于训练样本比较少,在网图上识别成这样的效果已经不错了,先写到这里。