基于深度学习的图像分割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分割、迁移学习等)
相关文章
|
8天前
|
人工智能 安全 Linux
【OpenClaw保姆级图文教程】阿里云/本地部署集成模型Ollama/Qwen3.5/百炼 API 步骤流程及避坑指南
2026年,AI代理工具的部署逻辑已从“单一云端依赖”转向“云端+本地双轨模式”。OpenClaw(曾用名Clawdbot)作为开源AI代理框架,既支持对接阿里云百炼等云端免费API,也能通过Ollama部署本地大模型,完美解决两类核心需求:一是担心云端API泄露核心数据的隐私安全诉求;二是频繁调用导致token消耗过高的成本控制需求。
5179 9
|
16天前
|
人工智能 JavaScript Ubuntu
5分钟上手龙虾AI!OpenClaw部署(阿里云+本地)+ 免费多模型配置保姆级教程(MiniMax、Claude、阿里云百炼)
OpenClaw(昵称“龙虾AI”)作为2026年热门的开源个人AI助手,由PSPDFKit创始人Peter Steinberger开发,核心优势在于“真正执行任务”——不仅能聊天互动,还能自动处理邮件、管理日程、订机票、写代码等,且所有数据本地处理,隐私完全可控。它支持接入MiniMax、Claude、GPT等多类大模型,兼容微信、Telegram、飞书等主流聊天工具,搭配100+可扩展技能,成为兼顾实用性与隐私性的AI工具首选。
21120 114
|
7天前
|
JavaScript Linux API
保姆级教程,通过GACCode在国内使用Claudecode、Codex!
保姆级教程,通过GACCode在国内使用Claudecode、Codex!
4676 1
保姆级教程,通过GACCode在国内使用Claudecode、Codex!
|
12天前
|
人工智能 安全 前端开发
Team 版 OpenClaw:HiClaw 开源,5 分钟完成本地安装
HiClaw 基于 OpenClaw、Higress AI Gateway、Element IM 客户端+Tuwunel IM 服务器(均基于 Matrix 实时通信协议)、MinIO 共享文件系统打造。
8067 7
|
14天前
|
人工智能 JavaScript API
保姆级教程:OpenClaw阿里云/本地部署配置Tavily Search skill 实时联网,让OpenClaw“睁眼看世界”
默认状态下的OpenClaw如同“闭门造车”的隐士,仅能依赖模型训练数据回答问题,无法获取实时新闻、最新数据或训练截止日期后的新信息。2026年,激活其联网能力的最优方案是配置Tavily Search技能——无需科学上网、无需信用卡验证,每月1000次免费搜索额度完全满足个人需求,搭配ClawHub技能市场,还能一键拓展天气查询、邮件管理等实用功能。
8112 5

热门文章

最新文章