基于深度学习的图像分割MATLAB程序,使用U-Net架构实现语义分割任务
%% 基于深度学习的图像分割 - U-Net实现
% 描述: 使用U-Net架构进行图像分割的完整实现
%% 清理工作区
clear; close all; clc;
%% 1. 数据准备
% 使用内置的硬币图像作为示例数据
img = imread('coins.png');
groundTruth = imread('coins.png'); % 实际应用中应使用真实标注
% 显示原始图像和标注
figure;
subplot(1,2,1); imshow(img); title('原始图像');
subplot(1,2,2); imshow(groundTruth); title('人工标注');
% 创建模拟数据集(实际应用中应使用真实数据集)
dataSet = createSyntheticDataset(10, [256, 256]);
% 划分训练集和测试集
[trainData, testData] = splitData(dataSet, 0.8);
% 创建数据存储
imds = imageDatastore({
trainData.images}, 'Labels', {
});
pxds = pixelLabelDatastore({
trainData.masks}, {
'Background', 'Object'}, [0 1]);
% 数据增强
augmenter = imageDataAugmenter(...
'RandRotation', [-20, 20], ...
'RandXTranslation', [-10, 10], ...
'RandYTranslation', [-10, 10], ...
'RandXScale', [0.8, 1.2], ...
'RandYScale', [0.8, 1.2], ...
'RandYReflection', true);
% 创建增强后的数据存储
augImds = augmentedImageDatastore([256, 256], imds);
augPxds = pixelLabelImageDatastore(pxds, augmentedImageDatastore([256, 256]));
%% 2. 构建U-Net网络
inputSize = [256, 256, 1]; % 输入图像尺寸
numClasses = 2; % 类别数(背景+目标)
% 使用MATLAB的U-Net实现
lgraph = unetLayers(inputSize, numClasses, 'EncoderDepth', 4);
% 自定义U-Net实现(可选)
% lgraph = buildCustomUNet(inputSize, numClasses);
% 显示网络结构
analyzeNetwork(lgraph);
%% 3. 设置训练选项
options = trainingOptions('adam', ...
'InitialLearnRate', 1e-3, ...
'MaxEpochs', 30, ...
'MiniBatchSize', 4, ...
'Shuffle', 'every-epoch', ...
'ValidationData', {
testData.images, testData.masks}, ...
'ValidationFrequency', 30, ...
'Verbose', true, ...
'Plots', 'training-progress', ...
'ExecutionEnvironment', 'auto'); % 自动选择CPU/GPU
%% 4. 训练网络
[net, info] = trainNetwork(augImds, augPxds, lgraph, options);
%% 5. 评估模型
% 在测试集上进行预测
predMasks = classifyPixels(net, testData.images);
% 计算性能指标
metrics = evaluateSegmentation(predMasks, testData.masks);
% 显示评估结果
disp('===== 分割性能评估 =====');
disp(['准确率(Accuracy): ', num2str(metrics.Accuracy)]);
disp(['精确率(Precision): ', num2str(metrics.Precision)]);
disp(['召回率(Recall): ', num2str(metrics.Recall)]);
disp(['F1分数(F1-score): ', num2str(metrics.F1score)]);
disp(['IoU(Jaccard Index): ', num2str(metrics.IoU)]);
%% 6. 可视化结果
visualizeResults(testData.images, testData.masks, predMasks);
%% 7. 保存模型
save('segmentationModel.mat', 'net');
%% 辅助函数定义
function dataset = createSyntheticDataset(numImages, imgSize)
% 创建合成数据集用于演示
dataset = struct('images', {
}, 'masks', {
});
for i = 1:numImages
% 创建随机形状
img = randi([200, 255], imgSize, 'uint8');
mask = false(imgSize);
% 添加圆形
centerX = randi([50, imgSize(2)-50]);
centerY = randi([50, imgSize(1)-50]);
radius = randi([20, 40]);
[x, y] = meshgrid(1:imgSize(2), 1:imgSize(1));
circle = (x - centerX).^2 + (y - centerY).^2 <= radius^2;
mask = mask | circle;
% 添加矩形
rectW = randi([30, 60]);
rectH = randi([30, 60]);
rectX = randi([10, imgSize(2)-rectW-10]);
rectY = randi([10, imgSize(1)-rectH-10]);
rect = false(imgSize);
rect(rectY:rectY+rectH, rectX:rectX+rectW) = true;
mask = mask | rect;
% 添加三角形
triX = [randi([20, imgSize(2)-20]), randi([20, imgSize(2)-20]), randi([20, imgSize(2)-20])];
triY = [randi([20, imgSize(1)-20]), randi([20, imgSize(1)-20]), randi([20, imgSize(1)-20])];
tri = poly2mask(triX, triY, imgSize(1), imgSize(2));
mask = mask | tri;
% 添加噪声
noise = randi([0, 50], imgSize, 'uint8');
img = img - noise;
img = max(0, min(255, img));
% 应用形状到图像
imgR = img;
imgG = img;
imgB = img;
imgR(mask) = 255;
imgG(mask) = 0;
imgB(mask) = 0;
img = cat(3, imgR, imgG, imgB);
% 二值化掩码
mask = uint8(mask) * 255;
% 添加到数据集
dataset(i).images = img;
dataset(i).masks = mask;
end
end
function [trainData, testData] = splitData(dataset, trainRatio)
% 划分训练集和测试集
numImages = length(dataset);
numTrain = round(numImages * trainRatio);
indices = randperm(numImages);
trainIndices = indices(1:numTrain);
testIndices = indices(numTrain+1:end);
trainData = struct('images', {
}, 'masks', {
});
testData = struct('images', {
}, 'masks', {
});
for i = 1:numTrain
trainData(i).images = dataset(trainIndices(i)).images;
trainData(i).masks = dataset(trainIndices(i)).masks;
end
for i = 1:(numImages - numTrain)
testData(i).images = dataset(testIndices(i)).images;
testData(i).masks = dataset(testIndices(i)).masks;
end
end
function lgraph = buildCustomUNet(inputSize, numClasses)
% 自定义U-Net实现
layers = [
% 编码器路径
imageInputLayer(inputSize, 'Name', 'input')
% 第一级下采样
convolution2dLayer(3, 64, 'Padding', 'same', 'Name', 'conv1_1')
batchNormalizationLayer('Name', 'bn1_1')
reluLayer('Name', 'relu1_1')
convolution2dLayer(3, 64, 'Padding', 'same', 'Name', 'conv1_2')
batchNormalizationLayer('Name', 'bn1_2')
reluLayer('Name', 'relu1_2')
maxPooling2dLayer(2, 'Stride', 2, 'Name', 'pool1')
% 第二级下采样
convolution2dLayer(3, 128, 'Padding', 'same', 'Name', 'conv2_1')
batchNormalizationLayer('Name', 'bn2_1')
reluLayer('Name', 'relu2_1')
convolution2dLayer(3, 128, 'Padding', 'same', 'Name', 'conv2_2')
batchNormalizationLayer('Name', 'bn2_2')
reluLayer('Name', 'relu2_2')
maxPooling2dLayer(2, 'Stride', 2, 'Name', 'pool2')
% 第三级下采样
convolution2dLayer(3, 256, 'Padding', 'same', 'Name', 'conv3_1')
batchNormalizationLayer('Name', 'bn3_1')
reluLayer('Name', 'relu3_1')
convolution2dLayer(3, 256, 'Padding', 'same', 'Name', 'conv3_2')
batchNormalizationLayer('Name', 'bn3_2')
reluLayer('Name', 'relu3_2')
maxPooling2dLayer(2, 'Stride', 2, 'Name', 'pool3')
% 第四级下采样
convolution2dLayer(3, 512, 'Padding', 'same', 'Name', 'conv4_1')
batchNormalizationLayer('Name', 'bn4_1')
reluLayer('Name', 'relu4_1')
convolution2dLayer(3, 512, 'Padding', 'same', 'Name', 'conv4_2')
batchNormalizationLayer('Name', 'bn4_2')
reluLayer('Name', 'relu4_2')
maxPooling2dLayer(2, 'Stride', 2, 'Name', 'pool4')
% 底部
convolution2dLayer(3, 1024, 'Padding', 'same', 'Name', 'conv5_1')
batchNormalizationLayer('Name', 'bn5_1')
reluLayer('Name', 'relu5_1')
convolution2dLayer(3, 1024, 'Padding', 'same', 'Name', 'conv5_2')
batchNormalizationLayer('Name', 'bn5_2')
reluLayer('Name', 'relu5_2')
% 解码器路径
transposedConv2dLayer(2, 512, 'Stride', 2, 'Name', 'upconv4')
concatenationLayer(3, 2, 'Name', 'concat4')
convolution2dLayer(3, 512, 'Padding', 'same', 'Name', 'conv_up4_1')
batchNormalizationLayer('Name', 'bn_up4_1')
reluLayer('Name', 'relu_up4_1')
convolution2dLayer(3, 512, 'Padding', 'same', 'Name', 'conv_up4_2')
batchNormalizationLayer('Name', 'bn_up4_2')
reluLayer('Name', 'relu_up4_2')
transposedConv2dLayer(2, 256, 'Stride', 2, 'Name', 'upconv3')
concatenationLayer(3, 2, 'Name', 'concat3')
convolution2dLayer(3, 256, 'Padding', 'same', 'Name', 'conv_up3_1')
batchNormalizationLayer('Name', 'bn_up3_1')
reluLayer('Name', 'relu_up3_1')
convolution2dLayer(3, 256, 'Padding', 'same', 'Name', 'conv_up3_2')
batchNormalizationLayer('Name', 'bn_up3_2')
reluLayer('Name', 'relu_up3_2')
transposedConv2dLayer(2, 128, 'Stride', 2, 'Name', 'upconv2')
concatenationLayer(3, 2, 'Name', 'concat2')
convolution2dLayer(3, 128, 'Padding', 'same', 'Name', 'conv_up2_1')
batchNormalizationLayer('Name', 'bn_up2_1')
reluLayer('Name', 'relu_up2_1')
convolution2dLayer(3, 128, 'Padding', 'same', 'Name', 'conv_up2_2')
batchNormalizationLayer('Name', 'bn_up2_2')
reluLayer('Name', 'relu_up2_2')
transposedConv2dLayer(2, 64, 'Stride', 2, 'Name', 'upconv1')
concatenationLayer(3, 2, 'Name', 'concat1')
convolution2dLayer(3, 64, 'Padding', 'same', 'Name', 'conv_up1_1')
batchNormalizationLayer('Name', 'bn_up1_1')
reluLayer('Name', 'relu_up1_1')
convolution2dLayer(3, 64, 'Padding', 'same', 'Name', 'conv_up1_2')
batchNormalizationLayer('Name', 'bn_up1_2')
reluLayer('Name', 'relu_up1_2')
% 输出层
convolution2dLayer(1, numClasses, 'Name', 'output_conv')
softmaxLayer('Name', 'softmax')
pixelClassificationLayer('Name', 'output')
];
% 连接跳跃连接
lgraph = layerGraph(layers);
lgraph = connectLayers(lgraph, 'relu1_2', 'concat1/in2');
lgraph = connectLayers(lgraph, 'relu2_2', 'concat2/in2');
lgraph = connectLayers(lgraph, 'relu3_2', 'concat3/in2');
lgraph = connectLayers(lgraph, 'relu4_2', 'concat4/in2');
end
function predMasks = classifyPixels(net, images)
% 使用训练好的网络进行像素分类
numImages = length(images);
predMasks = cell(1, numImages);
for i = 1:numImages
img = images{
i};
if size(img, 3) == 3
img = rgb2gray(img);
end
img = im2single(img);
img = imresize(img, [256, 256]);
img = cat(3, img, img, img); % 转换为3通道
% 预测
pred = semanticseg(img, net, 'MiniBatchSize', 1);
predMasks{
i} = pred;
end
end
function metrics = evaluateSegmentation(predMasks, trueMasks)
% 评估分割性能
numImages = length(predMasks);
confMat = zeros(2, 2); % 二分类混淆矩阵
for i = 1:numImages
predMask = predMasks{
i};
trueMask = trueMasks{
i};
% 二值化掩码
predBin = predMask > 0.5;
trueBin = trueMask > 128;
% 计算混淆矩阵
tp = sum(sum(predBin & trueBin));
fp = sum(sum(predBin & ~trueBin));
fn = sum(sum(~predBin & trueBin));
tn = sum(sum(~predBin & ~trueBin));
confMat(1,1) = confMat(1,1) + tp;
confMat(1,2) = confMat(1,2) + fp;
confMat(2,1) = confMat(2,1) + fn;
confMat(2,2) = confMat(2,2) + tn;
end
% 计算指标
accuracy = (confMat(1,1) + confMat(2,2)) / sum(confMat(:));
precision = confMat(1,1) / (confMat(1,1) + confMat(1,2));
recall = confMat(1,1) / (confMat(1,1) + confMat(2,1));
f1score = 2 * (precision * recall) / (precision + recall);
iou = confMat(1,1) / (confMat(1,1) + confMat(1,2) + confMat(2,1));
% 返回结果
metrics = struct(...
'Accuracy', accuracy, ...
'Precision', precision, ...
'Recall', recall, ...
'F1score', f1score, ...
'IoU', iou, ...
'ConfusionMatrix', confMat);
end
function visualizeResults(images, trueMasks, predMasks)
% 可视化分割结果
numImages = min(4, length(images)); % 最多显示4张图像
figure('Position', [100, 100, 1200, 800]);
for i = 1:numImages
% 原始图像
subplot(numImages, 3, (i-1)*3+1);
imshow(images{
i});
title(sprintf('原始图像 %d', i));
% 真实掩码
subplot(numImages, 3, (i-1)*3+2);
imshow(trueMasks{
i});
title('真实掩码');
% 预测掩码
subplot(numImages, 3, (i-1)*3+3);
imshow(labeloverlay(im2double(images{
i}), predMasks{
i}));
title('预测掩码');
end
% 单独显示预测结果
figure;
for i = 1:numImages
subplot(2, numImages, i);
imshow(images{
i});
title(sprintf('原始图像 %d', i));
subplot(2, numImages, numImages+i);
imshow(label2rgb(predMasks{
i}));
title(sprintf('预测结果 %d', i));
end
end
程序功能说明
1. 数据准备模块
- 合成数据生成:
createSyntheticDataset函数创建带有随机形状的合成图像数据集 - 数据划分:
splitData函数将数据划分为训练集和测试集 - 数据增强:使用
imageDataAugmenter进行随机旋转、平移和缩放
2. 网络构建模块
- U-Net实现:提供两种U-Net实现方式
- 使用MATLAB内置的
unetLayers函数 - 自定义U-Net实现
buildCustomUNet
- 使用MATLAB内置的
- 网络结构:编码器-解码器结构,包含跳跃连接
3. 训练配置模块
- 训练选项:使用Adam优化器,设置学习率、批次大小等参数
- 硬件加速:自动选择CPU或GPU进行训练
4. 评估与可视化模块
- 性能评估:
evaluateSegmentation计算准确率、精确率、召回率等指标 - 结果可视化:
visualizeResults显示原始图像、真实掩码和预测掩码
深度学习图像分割关键技术
1. U-Net架构
U-Net是一种专为生物医学图像分割设计的卷积神经网络,其特点包括:
- 对称的编码器-解码器结构
- 跳跃连接融合低级和高级特征
- 适用于小样本数据集
2. 损失函数
本程序使用交叉熵损失函数,适用于多类分割任务:

其中 $y_i,c$是真实标签,$p_i,c$是预测概率
3. 数据增强
为增加数据多样性,提高模型泛化能力,采用以下增强技术:
- 随机旋转(-20°到20°)
- 随机平移(±10像素)
- 随机缩放(0.8-1.2倍)
- 随机水平翻转
参考代码 利用深度学习的matlab程序编码仿真实现图像分割 www.youwenfan.com/contentalh/95829.html
实际应用扩展
1. 使用真实数据集
% 加载真实数据集(示例)
data = load('CamVid.mat'); % CamVid道路场景数据集
images = data.images;
labels = data.labels;
% 创建数据存储
imds = imageDatastore(images);
pxds = pixelLabelDatastore(labels, categories, labelIDs);
2. 迁移学习
% 加载预训练模型
pretrainedNet = resnet50;
% 修改最后几层
lgraph = layerGraph(pretrainedNet);
newLayers = [
convolution2dLayer(1, 64, 'Name', 'new_conv1')
reluLayer('Name', 'new_relu1')
transposedConv2dLayer(2, 32, 'Stride', 2, 'Name', 'new_upconv1')
convolution2dLayer(3, 32, 'Padding', 'same', 'Name', 'new_conv2')
reluLayer('Name', 'new_relu2')
convolution2dLayer(1, numClasses, 'Name', 'final_conv')
softmaxLayer('Name', 'softmax')
pixelClassificationLayer('Name', 'output')
];
lgraph = replaceLayer(lgraph, 'fc1000', newLayers);
3. 多类分割
% 设置多类分割参数
numClasses = 5; % 例如:背景、道路、车辆、行人、建筑
classNames = {
'Background', 'Road', 'Vehicle', 'Pedestrian', 'Building'};
labelIDs = [0, 1, 2, 3, 4];
% 修改输出层
outputLayer = pixelClassificationLayer('Name', 'output', ...
'ClassNames', classNames, ...
'OutputSize', numClasses);
4. 3D图像分割(医学影像)
% 使用3D U-Net进行体积分割
inputSize = [128, 128, 64, 1]; % 高度、宽度、深度、通道
lgraph = unet3dLayers(inputSize, numClasses);
% 训练3D网络
options = trainingOptions('adam', ...
'MaxEpochs', 20, ...
'MiniBatchSize', 1, ... % 3D网络需要更小的批次
'Plots', 'training-progress');
net = trainNetwork(volumeData, lgraph, options);
性能优化技巧
混合精度训练:
options = trainingOptions('adam', ... 'GradientDataType', 'single', ... 'GradientDecayFactor', 0.9, ... 'SquaredGradientDecayFactor', 0.999);学习率调度:
options = trainingOptions('adam', ... 'LearnRateSchedule', 'piecewise', ... 'LearnRateDropPeriod', 10, ... 'LearnRateDropFactor', 0.1);模型量化:
% 训练后量化模型 quantizedNet = quantize(net, 'Method', 'Linear');硬件加速:
- 使用GPU加速:
'ExecutionEnvironment', 'gpu' - 多GPU训练:
'ExecutionEnvironment', 'multi-gpu'
- 使用GPU加速:
常见问题解决方案
- 内存不足:
- 减小批次大小
- 降低图像分辨率
- 使用梯度累积
- 训练不稳定:
- 添加批归一化层
- 使用学习率预热
- 添加正则化(Dropout)
- 过拟合:
- 增加数据增强强度
- 添加Dropout层
- 使用早停策略
- 分割边界不精确:
- 使用CRF后处理
- 添加边缘感知损失
- 使用注意力机制
结论
本程序提供了一个完整的基于深度学习的图像分割解决方案,具有以下特点:
- 实现了经典的U-Net架构
- 包含数据准备、网络训练、评估和可视化全流程
- 支持合成数据生成和真实数据应用
- 提供多种扩展选项(多类分割、3D分割、迁移学习等)