基于深度学习的图像分割MATLAB实现

基于深度学习的图像分割MATLAB程序,使用U-Net架构实现语义分割任务

matlab 复制代码
%% 基于深度学习的图像分割 - 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
  • 网络结构:编码器-解码器结构,包含跳跃连接

3. 训练配置模块

  • 训练选项:使用Adam优化器,设置学习率、批次大小等参数
  • 硬件加速:自动选择CPU或GPU进行训练

4. 评估与可视化模块

  • 性能评估evaluateSegmentation计算准确率、精确率、召回率等指标
  • 结果可视化visualizeResults显示原始图像、真实掩码和预测掩码

深度学习图像分割关键技术

1. U-Net架构

U-Net是一种专为生物医学图像分割设计的卷积神经网络,其特点包括:

  • 对称的编码器-解码器结构
  • 跳跃连接融合低级和高级特征
  • 适用于小样本数据集

2. 损失函数

本程序使用交叉熵损失函数,适用于多类分割任务:

其中 yi,cy_i,cyi,c是真实标签,pi,cp_i,cpi,c是预测概率

3. 数据增强

为增加数据多样性,提高模型泛化能力,采用以下增强技术:

  • 随机旋转(-20°到20°)
  • 随机平移(±10像素)
  • 随机缩放(0.8-1.2倍)
  • 随机水平翻转

参考代码 利用深度学习的matlab程序编码仿真实现图像分割 www.youwenfan.com/contentcss/95829.html

实际应用扩展

1. 使用真实数据集

matlab 复制代码
% 加载真实数据集(示例)
data = load('CamVid.mat'); % CamVid道路场景数据集
images = data.images;
labels = data.labels;

% 创建数据存储
imds = imageDatastore(images);
pxds = pixelLabelDatastore(labels, categories, labelIDs);

2. 迁移学习

matlab 复制代码
% 加载预训练模型
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. 多类分割

matlab 复制代码
% 设置多类分割参数
numClasses = 5; % 例如:背景、道路、车辆、行人、建筑
classNames = {'Background', 'Road', 'Vehicle', 'Pedestrian', 'Building'};
labelIDs = [0, 1, 2, 3, 4];

% 修改输出层
outputLayer = pixelClassificationLayer('Name', 'output', ...
    'ClassNames', classNames, ...
    'OutputSize', numClasses);

4. 3D图像分割(医学影像)

matlab 复制代码
% 使用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);

性能优化技巧

  1. 混合精度训练

    matlab 复制代码
    options = trainingOptions('adam', ...
        'GradientDataType', 'single', ...
        'GradientDecayFactor', 0.9, ...
        'SquaredGradientDecayFactor', 0.999);
  2. 学习率调度

    matlab 复制代码
    options = trainingOptions('adam', ...
        'LearnRateSchedule', 'piecewise', ...
        'LearnRateDropPeriod', 10, ...
        'LearnRateDropFactor', 0.1);
  3. 模型量化

    matlab 复制代码
    % 训练后量化模型
    quantizedNet = quantize(net, 'Method', 'Linear');
  4. 硬件加速

    • 使用GPU加速:'ExecutionEnvironment', 'gpu'
    • 多GPU训练:'ExecutionEnvironment', 'multi-gpu'

常见问题解决方案

  1. 内存不足
    • 减小批次大小
    • 降低图像分辨率
    • 使用梯度累积
  2. 训练不稳定
    • 添加批归一化层
    • 使用学习率预热
    • 添加正则化(Dropout)
  3. 过拟合
    • 增加数据增强强度
    • 添加Dropout层
    • 使用早停策略
  4. 分割边界不精确
    • 使用CRF后处理
    • 添加边缘感知损失
    • 使用注意力机制

结论

本程序提供了一个完整的基于深度学习的图像分割解决方案,具有以下特点:

  1. 实现了经典的U-Net架构
  2. 包含数据准备、网络训练、评估和可视化全流程
  3. 支持合成数据生成和真实数据应用
  4. 提供多种扩展选项(多类分割、3D分割、迁移学习等)
相关推荐
词元Max2 小时前
1.2 深度学习核心概念:神经网络直觉理解
人工智能·深度学习·神经网络
x-cmd2 小时前
[260326] x-cmd v0.8.10:跨 Shell 统一配置命令短名;自动装好依赖运行 WhisperLiveKit 实时语音转写
linux·人工智能·ai·whisper·shortcut·x-cmd
同元软控2 小时前
即将开源:Sysplorer MCP Server+智能体重塑系统建模仿真工作流
人工智能·开源·mworks
Dway2 小时前
范数-归一化
人工智能·深度学习·机器学习·范数·l2归一化
清空mega2 小时前
李沐《动手学深度学习》——实战 Kaggle 比赛:预测房价
人工智能·深度学习
lifallen2 小时前
Agent plantask 的架构推导
人工智能·语言模型·架构
AImatters2 小时前
出海营销变天了:当Agentic AI重构创意、投放与归因
人工智能·亚马逊云科技·出海·agentic ai·易点天下
你们补药再卷啦2 小时前
上下文工程(1/4)笔记
人工智能
以为你知道啊2 小时前
从源代码自动生成 OpenAPI 3.1.0 规范文件 + Redoc 可视化文档的技能
人工智能