MATLAB进行图像分割从基础阈值到高级分割

图像分割是将图像划分为若干个具有不同特征的区域(如前景/背景、目标/背景)的核心技术,MATLAB的Image Processing Toolbox提供了丰富的分割函数,覆盖阈值分割、边缘分割、区域分割、聚类分割等主流方法。

一、图像分割基础准备

1. 核心概念与数据准备

  • 分割目标:将图像中感兴趣的目标(如硬币、车牌、细胞)从背景中分离;
  • 图像类型:优先使用灰度图(二维矩阵)进行分割,RGB图需先转换为灰度图;
  • 预处理:分割前通常需去噪(中值滤波、高斯滤波)、增强对比度(直方图均衡化),提升分割效果。
matlab 复制代码
% 基础准备:读取图像并预处理
img = imread('coins.png'); % 读取MATLAB内置灰度图(硬币示例)
img = im2double(img); % 转换为double型(便于计算)

% 预处理:去噪+对比度增强
img_denoise = medfilt2(img, [3 3]); % 3×3中值滤波去噪
img_enhance = adapthisteq(img_denoise); % CLAHE对比度增强

% 显示预处理结果
figure;
subplot(1,2,1); imshow(img); title('原始图像');
subplot(1,2,2); imshow(img_enhance); title('预处理后图像');

二、基础分割:阈值分割(最常用)

阈值分割是通过设定灰度值阈值,将图像分为"大于阈值"和"小于阈值"两部分,适合目标与背景灰度差异明显的场景(如黑白对比强烈的图像)。

1. 手动阈值分割

适用于已知目标/背景灰度范围的场景,手动调整阈值实现分割。

matlab 复制代码
% 手动设定阈值(0.4,需根据图像灰度范围调整)
threshold = 0.4;
img_binary = img_enhance > threshold; % 二值化:大于阈值为1(白色),小于为0(黑色)

% 显示分割结果
figure;
subplot(1,2,1); imshow(img_enhance); title('预处理图像');
subplot(1,2,2); imshow(img_binary); title('手动阈值分割(阈值=0.4)');

2. 自动阈值分割(Otsu方法,推荐)

MATLAB内置graythresh函数实现Otsu算法,自动计算最优阈值(适合双峰灰度直方图的图像)。

matlab 复制代码
% 步骤1:计算最优阈值
level = graythresh(img_enhance); % 输出0-1之间的归一化阈值
fprintf('Otsu自动计算的阈值:%.4f\n', level);

% 步骤2:二值化分割
img_otsu = imbinarize(img_enhance, level);

% 步骤3:形态学操作优化(去除小噪点、填补孔洞)
se = strel('disk', 2); % 2×2圆盘结构元素
img_otsu_clean = imopen(img_otsu, se); % 开运算(先腐蚀后膨胀,去除小噪点)
img_otsu_clean = imfill(img_otsu_clean, 'holes'); % 填补孔洞

% 对比分割效果
figure;
subplot(1,3,1); imshow(img_enhance); title('预处理图像');
subplot(1,3,2); imshow(img_otsu); title('Otsu原始分割');
subplot(1,3,3); imshow(img_otsu_clean); title('形态学优化后');

3. 自适应阈值分割(应对光照不均)

当图像光照不均(如局部亮、局部暗)时,全局阈值分割效果差,使用adaptthresh实现局部自适应阈值。

matlab 复制代码
% 自适应阈值分割(窗口大小15×15,偏移量0.05)
level_adapt = adaptthresh(img_enhance, 0.05, 'NeighborhoodSize', 15);
img_adapt = imbinarize(img_enhance, level_adapt);

% 显示效果(对比全局Otsu)
figure;
subplot(1,2,1); imshow(img_otsu_clean); title('全局Otsu分割');
subplot(1,2,2); imshow(img_adapt); title('自适应阈值分割');

三、边缘基分割:基于边缘检测的分割

通过检测图像边缘(灰度突变处)实现分割,适合目标轮廓清晰的场景,核心使用edge函数结合Canny/Sobel算子。

matlab 复制代码
% 步骤1:边缘检测(Canny算子,最优边缘检测效果)
edges_canny = edge(img_enhance, 'canny', [0.1, 0.3]); % 高低阈值0.1/0.3

% 步骤2:边缘连接与闭合(形态学膨胀)
se = strel('line', 3, 0); % 3像素线结构元素
edges_dilate = imdilate(edges_canny, se); % 膨胀连接断裂边缘

% 步骤3:填充边缘包围的区域(得到分割结果)
img_edge_seg = imfill(edges_dilate, 'holes');

% 显示边缘分割流程
figure;
subplot(1,3,1); imshow(edges_canny); title('Canny边缘检测');
subplot(1,3,2); imshow(edges_dilate); title('边缘膨胀连接');
subplot(1,3,3); imshow(img_edge_seg); title('边缘分割结果');

四、区域基分割:区域生长与连通域分析

1. 区域生长分割

从种子点出发,将灰度相似的像素合并为一个区域,适合目标区域灰度均匀的场景。

matlab 复制代码
% 步骤1:选择种子点(手动选1个硬币的中心像素)
% 先显示图像,点击选择种子点坐标
figure; imshow(img_enhance); title('点击选择种子点');
[x, y] = ginput(1); % 手动点击获取坐标
seed_x = round(x); % 取整
seed_y = round(y);
fprintf('选择的种子点坐标:(%d, %d)\n', seed_x, seed_y);

% 步骤2:区域生长(灰度差阈值5)
img_region = regiongrowing(img_enhance, seed_x, seed_y, 5); % 自定义区域生长函数

% 自定义区域生长函数(核心)
function J = regiongrowing(I, x, y, t)
    [M, N] = size(I);
    J = zeros(M, N); % 初始化分割结果
    J(y, x) = 1; % 标记种子点
    seed_val = I(y, x); % 种子点灰度值
    queue = [y, x]; % 队列存储待扩展像素
    
    % 4邻域扩展
    dirs = [[-1,0], [1,0], [0,-1], [0,1]];
    
    while ~isempty(queue)
        % 取出队列首像素
        curr_y = queue(1,1);
        curr_x = queue(1,2);
        queue(1,:) = [];
        
        % 遍历4邻域
        for d = 1:4
            ny = curr_y + dirs(d,1);
            nx = curr_x + dirs(d,2);
            
            % 检查坐标是否在图像内,且未被标记,且灰度差小于阈值
            if ny >= 1 && ny <= M && nx >= 1 && nx <= N && J(ny, nx) == 0 && abs(I(ny, nx) - seed_val) < t
                J(ny, nx) = 1;
                queue = [queue; ny, nx];
            end
        end
    end
    J = logical(J); % 转换为逻辑型
end

% 显示区域生长结果
figure;
subplot(1,2,1); imshow(img_enhance); hold on; plot(seed_x, seed_y, 'r*', 'MarkerSize', 10); title('种子点位置');
subplot(1,2,2); imshow(img_region); title('区域生长分割结果');

2. 连通域分析(分割多个目标)

对二值化图像进行连通域标记,提取每个目标的区域特征(面积、中心、边界框),适合多目标分割。

matlab 复制代码
% 基于Otsu分割后的图像进行连通域分析
[L, num] = bwlabel(img_otsu_clean); % L为标记矩阵,num为连通域数量
fprintf('检测到的连通域数量:%d\n', num);

% 提取连通域特征(中心、面积、边界框)
stats = regionprops(L, 'Centroid', 'Area', 'BoundingBox');

% 绘制连通域标记结果
img_labeled = imlabeloverlay(img_enhance, L); % 叠加标记到原图
figure; imshow(img_labeled); title(sprintf('连通域分割(共%d个目标)', num));

% 绘制每个目标的边界框
hold on;
for i = 1:num
    bbox = stats(i).BoundingBox;
    rectangle('Position', bbox, 'EdgeColor', 'r', 'LineWidth', 2);
end
hold off;

% 筛选面积大于100的目标(去除小噪点)
min_area = 100;
img_filtered = ismember(L, find([stats.Area] > min_area));
figure; imshow(img_filtered); title('筛选后分割结果(面积>100)');

五、高级分割:K-Means聚类分割(适合彩色图像)

K-Means聚类分割无需设定阈值,通过聚类将像素分为K类(如前景/背景),适合彩色图像或灰度分布复杂的图像。

matlab 复制代码
% 以彩色图像为例(MATLAB内置peppers.jpg)
img_rgb = imread('peppers.jpg');
img_rgb = im2double(img_rgb);

% 步骤1:将图像转换为像素向量(行×列,3通道)
[M, N, C] = size(img_rgb);
img_vec = reshape(img_rgb, M*N, C); % 转换为(M*N)×3的矩阵

% 步骤2:K-Means聚类(K=2,分为前景/背景)
k = 2;
[idx, centers] = kmeans(img_vec, k); % idx为每个像素的聚类标签,centers为聚类中心

% 步骤3:重构分割图像
img_kmeans = reshape(idx, M, N); % 转换回图像尺寸
img_kmeans = imbinarize(img_kmeans, 1.5); % 转换为二值图(1类为背景,2类为前景)

% 显示K-Means分割结果
figure;
subplot(1,2,1); imshow(img_rgb); title('原始彩色图像');
subplot(1,2,2); imshow(img_kmeans); title('K-Means聚类分割(K=2)');

六、分割效果评估(可选)

通过交集并集比(IoU) 评估分割精度(需有标注的真实分割图),无标注时可通过视觉对比+连通域特征判断。

matlab 复制代码
% 假设mask_true为真实分割标签(二值图),mask_pred为预测分割结果
% IoU = 交集面积 / 并集面积
% 以Otsu分割结果为例,模拟真实标签(取前5个硬币为真实目标)
mask_true = false(size(img_otsu_clean));
mask_true(10:80, 10:80) = true; % 模拟真实目标区域
mask_pred = img_otsu_clean;

% 计算IoU
intersection = sum(sum(mask_true & mask_pred));
union = sum(sum(mask_true | mask_pred));
iou = intersection / union;
fprintf('分割IoU:%.4f\n', iou);

七、常见问题与避坑指南

问题现象 核心原因 解决方案
阈值分割结果有大量噪点 图像未去噪/阈值设置不当 先中值滤波去噪,使用Otsu自动阈值替代手动阈值
边缘分割轮廓断裂 边缘检测阈值过高/图像噪声多 降低Canny算子低阈值,先做高斯滤波平滑图像
区域生长分割漏检目标 种子点选择不当/灰度阈值太小 选择目标中心像素作为种子点,适当增大灰度差阈值
K-Means分割结果混乱 K值设置错误/未归一化像素值 先将像素值归一化到0-1,通过试错确定最优K值(如K=2/3)
连通域数量过多 二值图有小噪点/孔洞 形态学开运算去除小噪点,imfill填补孔洞后再做连通域分析
相关推荐
listhi5203 小时前
针对燃油运输和车辆调度问题的蚁群算法MATLAB实现
前端·算法·matlab
Dillon Dong4 小时前
Simulink进阶:从零打造你的自定义模块库并集成到浏览器
matlab·simulink
骄傲的心别枯萎4 小时前
RV1126 NO.56:ROCKX+RV1126人脸识别推流项目之VI模块和VENC模块讲解
人工智能·opencv·计算机视觉·音视频·rv1126
骄傲的心别枯萎4 小时前
RV1126 NO.55:ROCKX+RV1126人脸识别推流项目讲解
opencv·计算机视觉·音视频·rv1126
bryant_meng5 小时前
【Depth Estimation】learning notes
人工智能·深度学习·计算机视觉·深度估计·depth anything
码界奇点6 小时前
Python与OpenCV集成海康威视工业相机从基础配置到高级应用的全方位指南
python·数码相机·opencv·相机·python3.11
ccLianLian7 小时前
ResCLIP
人工智能·计算机视觉
棒棒的皮皮7 小时前
【OpenCV】Python图像处理几何变换之透视
图像处理·python·opencv·计算机视觉
Evand J7 小时前
【EKF定位滤波例程】三维空间(XYZ)速度与位置观测与滤波(使用扩展卡尔曼滤波EKF),状态量和观测量都是非线性的。附MATLAB例程下载链接
开发语言·matlab