基于深度学习的图像分割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分割、迁移学习等)
相关推荐
一次旅行几秒前
2026‑08‑22 AI产业深度解读|Anthropic自研芯片布局、SGLang权重缓存守护进程、Agent任务作弊审计、AI原生SDLC
人工智能·缓存·sglang
Dawson Zhu2 分钟前
【AI架构前沿】MEMO:解耦推理与记忆,破解大模型“知识更新“与“灾难性遗忘“的两难困境
人工智能·架构·aigc·agi
江湖有缘5 分钟前
跨平台AI终端Wave:智能SSH与文件管理
运维·人工智能·ssh
IT_陈寒12 分钟前
Python装饰器把我坑惨了,原来这样用才不掉链子
前端·人工智能·后端
吃旺旺雪饼的小男孩13 分钟前
自动驾驶图像分割开源数据集指南(2026)
人工智能·开源·自动驾驶
A133455514 分钟前
视频特效字幕怎么翻译?保姆级AI字幕与外挂字幕教程
人工智能·音视频
飞哥数智坊16 分钟前
我给 DeepSeek 看了两次截图,才发现 Vision 真正的价值
人工智能·ai编程·deepseek
飞哥数智坊27 分钟前
AI提升了人效,但组织却接不住释放的生产力
人工智能
飞哥数智坊35 分钟前
什么才叫真正的端到端?
人工智能
武科大许志伟1 小时前
从并行进化到分布式进化计算读 A Survey on Distributed Evolutionary Computation
人工智能·分布式·演化计算