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

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

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

3. 训练配置模块

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

4. 评估与可视化模块

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

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

1. U-Net架构

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

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

2. 损失函数

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

download.png

其中 $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);

性能优化技巧

  1. 混合精度训练

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

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

    % 训练后量化模型
    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分割、迁移学习等)
相关文章
|
7月前
|
计算机视觉
MATLAB实现图像分割:Otsu阈值法
Otsu方法(大津法)是一种广泛使用的自动图像阈值分割技术,它通过最大化类间方差来确定最佳阈值。
|
2月前
|
消息中间件 存储 IDE
STM32F107加载UCOS系统并实现CAN总线通信
STM32F107加载UCOS系统并实现CAN总线通信
|
4月前
|
机器学习/深度学习 边缘计算 安全
C#实现OPC客户端
C#实现OPC客户端,结合OPC DA与OPC UA两种协议
|
2月前
|
机器学习/深度学习 传感器 算法
无线通信系统信道估计算法详解
信道估计是无线通信系统的核心技术之一,其目的是通过接收信号推断信道的冲激响应或频率响应,为相干解调、波束赋形、资源分配等功能提供信道状态信息(CSI)。在4G/5G/6G系统中,信道估计的精度直接影响通信质量(如误码率、吞吐量),而随着大规模MIMO、毫米波、超密集组网等技术的普及,信道估计的复杂度与实时性要求也日益提高。
|
2月前
|
网络协议 物联网 编译器
STM32 MQTT客户端实现方案(基于二次开发包)
STM32 MQTT客户端实现方案(基于二次开发包)
|
1月前
|
Web App开发 人工智能 安全
LINE 多开怎么实现?五种方案一次讲清!(含个人号与官方号)
跨境业务工具太分散?这篇文章教你用 OpenClaw 串联引流、客服、数据分析与自动化,通过 4个 OpenClaw Skill 搭建完整的跨境业务闭环。
437 2
|
29天前
基于MATLAB的激光器锁模技术仿真
锁模技术通过锁定激光谐振腔内纵模相位差,产生超短脉冲。MATLAB仿真主要基于**非线性薛定谔方程(NLSE)**,结合分步傅里叶法(SSFM)或龙格-库塔法(RK4)求解脉冲传播过程
|
1月前
|
机器学习/深度学习 传感器 边缘计算
终端电气综合治理装置系统医院谐波治理方案,沃思智能
沃思智能电气综合治理技术重塑现代医院:心电监护实时云端预警、手术机器人精度达0.1毫米、配电响应快至15毫秒、能效提升35%、检验提速60%。以智能稳压、滤波与预测性维护,筑牢医疗安全与效率的电力基石。(239字)
108 3
|
1月前
|
人工智能 语音技术
AI英语口语APP的主要功能
这是一款高实时、强交互的AI英语口语私教APP:毫秒级双工对话、情感化语音、音素级纠音、多模态场景训练(含视觉识别)、全真备考模考及自适应学习路径,聚焦“降低开口压力”,以同理心设计重塑语言学习体验。(239字)
|
2月前
|
传感器 机器学习/深度学习 算法
基于MATLAB的复杂环境移动机器人路径规划算法研究
针对复杂环境下移动机器人的路径规划问题,本文研究了全局路径规划(A*算法、Dijkstra算法)与局部路径规划(动态窗口法DWA、人工势场法APF)的经典算法,并结合MATLAB仿真平台实现了算法验证与性能对比。通过构建栅格地图与动态障碍物环境,分析了不同算法的路径长度、计算时间、避障能力等性能指标,提出了一种混合路径规划策略(全局A*+局部DWA),有效提升了机器人在复杂环境下的路径安全性与实时性。实验结果表明,混合策略在路径长度与避障成功率上优于单一算法,为复杂环境机器人导航提供了可行方案。