matlab,语义分割

打开MATLAB时总有人觉得它只是个数学计算工具,但当你把摄像头对准它的Deep Learning Toolbox工具箱,会发现这家伙早就偷偷进化成了图像处理领域的六边形战士。今天咱们直接动手玩点刺激的——用MATLAB给图像里的每个像素发身份证。

先整点硬核的,试试预训练模型开箱即用。掏出下面这串代码直接给草莓图片做CT:

img = imread('strawberries.jpg');
net = load('deeplabv3plusResnet18CamVid.mat');
[segMap,~] = semanticseg(img, net);
overlay = labeloverlay(img, segMap);
imshow(overlay)

注意看semanticseg这个函数,它像像素级侦探一样,把图片里的草莓、叶子、背景挨个标上不同颜色。运行完这段代码,你会看到原本红彤彤的草莓图片突然变成了抽象派水彩画——不同颜色区块代表着算法识别出的不同语义区域。

matlab,语义分割

但别被预训练模型惯坏了,真正有意思的是自己调教模型。打开Image Labeler应用手动标注200张盆栽图片,记得把"多肉"、"陶盆"、"背景"三个类别标清楚。数据准备好后上硬菜:

imds = imageDatastore('potted_plants/');
pxds = pixelLabelDatastore('labels/', {'succulent','pot','background'}, [1 2 3]);
[imdsTrain, imdsVal, pxdsTrain, pxdsVal] = partitionData(imds, pxds, 0.8);

layers = [
    imageInputLayer([256 256 3])
    convolution2dLayer(3,32,'Padding','same')
    reluLayer
    maxPooling2dLayer(2,'Stride',2)
    % 中间省略5个卷积块
    transposeConv2dLayer(4,32,'Stride',2,'Cropping',1)
    convolution2dLayer(1,3)
    softmaxLayer()
    pixelClassificationLayer()
];

options = trainingOptions('sgdm', ...
    'InitialLearnRate',1e-3,...
    'MaxEpochs',20,...
    'ValidationData',{imdsVal,pxdsVal});

model = trainNetwork(imdsTrain, pxdsTrain, layers, options);

这段代码里藏着几个魔鬼细节:transposeConv2dLayer负责把压缩的特征图放大回原图尺寸,就像把碎纸机里的文件复原;最后的1x1卷积层convolution2dLayer(1,3)其实是在做像素级别的分类决策,3对应我们定义的三个类别。训练时如果爆显存,把图片尺寸降到128x128能救命。

测试阶段遇到边缘锯齿?试试形态学后处理:

segMap = semanticseg(testImg, model);
mask = segMap == 'succulent';
se = strel('disk',2);
smoothMask = imopen(mask, se);
imshowpair(testImg, smoothMask, 'blend')

这个腐蚀膨胀操作能让多肉植物的边缘变得丝滑,原理就像用修正液涂抹参差不齐的边界。不过要注意结构元素strel的尺寸别设太大,否则会把细枝末节都抹平了。

最后给实战派留个作业:尝试在数据增强部分加入随机光照变化,用下面这个transform函数给训练数据加点料:

aug = imageDataAugmenter(...
    'RandRotation',[-20 20],...
    'RandXReflection',true,...
    'RandScale',[0.8 1.2],...
    'RandBrightness',[0.7 1.3]);

调参时盯着验证集IoU指标别眨眼,当发现训练损失还在降但验证指标开始波动时,果断掐掉训练防止过拟合——这分寸把握得像在悬崖边玩平衡木。记住,好的语义分割模型不仅要眼尖,还得手稳。

更多推荐