MATLAB实现图像分割:Otsu阈值法

简介: Otsu方法(大津法)是一种广泛使用的自动图像阈值分割技术,它通过最大化类间方差来确定最佳阈值。

Otsu方法(大津法)是一种广泛使用的自动图像阈值分割技术,它通过最大化类间方差来确定最佳阈值。

Otsu方法原理

Otsu方法的基本思想是将图像像素分为前景和背景两类,通过寻找使两类间方差最大的阈值来实现最佳分割。

数学原理

  1. 设图像有L个灰度级(通常为0-255)

  2. 设阈值为T,将像素分为两类:

    • C₀: 灰度值在[0, T]之间的像素
    • C₁: 灰度值在[T+1, L-1]之间的像素
  3. 计算两类间的方差:

    σ²_b(T) = ω₀(μ₀ - μ_T)² + ω₁(μ₁ - μ_T)²
    

    其中:

    • ω₀, ω₁: 两类像素的概率
    • μ₀, μ₁: 两类像素的平均灰度
    • μ_T: 整幅图像的平均灰度
  4. 寻找使σ²_b(T)最大的T值作为最佳阈值

MATLAB中的Otsu阈值实现

MATLAB提供了内置函数graythresh来实现Otsu方法,该函数返回归一化的阈值(范围0-1)。

基本使用示例

% 读取图像
I = imread('coins.png');
figure;
subplot(2, 2, 1);
imshow(I);
title('原始图像');

% 转换为灰度图像(如果必要)
if size(I, 3) == 3
    I_gray = rgb2gray(I);
else
    I_gray = I;
end

% 使用graythresh计算Otsu阈值
level = graythresh(I_gray);
fprintf('Otsu阈值 (0-1范围): %.4f\n', level);
fprintf('Otsu阈值 (0-255范围): %.4f\n', level * 255);

% 应用阈值进行分割
BW = imbinarize(I_gray, level);

% 显示结果
subplot(2, 2, 2);
imshow(BW);
title('Otsu阈值分割结果');

% 显示灰度直方图和阈值位置
subplot(2, 2, 3);
imhist(I_gray);
hold on;
line([level*255, level*255], ylim, 'Color', 'r', 'LineWidth', 2);
title('灰度直方图与阈值');
hold off;

% 显示原始图像与分割结果的叠加
subplot(2, 2, 4);
imshow(I);
hold on;
% 创建分割边界覆盖图
boundaries = bwboundaries(BW);
for k = 1:length(boundaries)
    boundary = boundaries{
   k};
    plot(boundary(:,2), boundary(:,1), 'r', 'LineWidth', 1.5);
end
title('分割边界叠加');
hold off;

自定义Otsu阈值函数实现

为了更好地理解Otsu方法,我们可以自己实现一个Otsu阈值计算函数:

function [threshold, max_var] = otsu_threshold(image)
    % OTSU_THRESHOLD 自定义Otsu阈值计算函数
    % 输入: image - 灰度图像矩阵
    % 输出: threshold - 计算得到的最佳阈值
    %       max_var - 最大类间方差

    % 计算图像直方图
    [counts, binLocations] = imhist(image);

    % 归一化直方图,得到概率分布
    p = counts / sum(counts);

    % 初始化变量
    max_var = 0;
    threshold = 0;
    total_mean = sum((0:255)' .* p); % 整体均值

    % 遍历所有可能的阈值
    for T = 1:256
        % 计算两类概率
        w0 = sum(p(1:T));
        w1 = sum(p(T+1:end));

        if w0 == 0 || w1 == 0
            continue;
        end

        % 计算两类均值
        mu0 = sum((0:T-1)' .* p(1:T)) / w0;
        mu1 = sum((T:255)' .* p(T+1:end)) / w1;

        % 计算类间方差
        between_var = w0 * w1 * (mu0 - mu1)^2;

        % 更新最大方差和阈值
        if between_var > max_var
            max_var = between_var;
            threshold = T - 1; % 转换为0-255范围的阈值
        end
    end
end

使用自定义函数:

% 使用自定义Otsu函数
[custom_threshold, max_var] = otsu_threshold(I_gray);
fprintf('自定义Otsu阈值: %.4f\n', custom_threshold);
fprintf('最大类间方差: %.4f\n', max_var);

% 应用自定义阈值
BW_custom = I_gray > custom_threshold;

% 比较MATLAB内置函数和自定义函数的结果
figure;
subplot(1, 2, 1);
imshow(BW);
title(['MATLAB内置函数: ', num2str(level*255)]);
subplot(1, 2, 2);
imshow(BW_custom);
title(['自定义函数: ', num2str(custom_threshold)]);

多阈值Otsu方法

对于更复杂的图像,可能需要使用多阈值Otsu方法:

function thresholds = multi_otsu(image, n)
    % MULTI_OTSU 多阈值Otsu方法
    % 输入: image - 灰度图像
    %       n - 阈值数量(分割区域数为n+1% 输出: thresholds - 阈值向量

    % 计算直方图
    [counts, ~] = imhist(image);
    p = counts / sum(counts);

    % 初始化
    thresholds = zeros(1, n);
    max_var = 0;

    % 生成所有可能的阈值组合(简化版本,实际应用中可能需要优化算法)
    % 这里使用递归方法搜索最佳阈值组合
    thresholds = recursive_otsu(p, 1, 256, n, []);
end

function best_thresholds = recursive_otsu(p, start, finish, n, current)
    % 递归辅助函数
    if n == 0
        % 计算当前阈值组合的类间方差
        var = calculate_variance(p, current);
        best_thresholds = {
   current, var};
        return;
    end

    best_var = -1;
    best_combination = [];

    for t = start:finish-n
        new_current = [current, t];
        [combination, var] = recursive_otsu(p, t+1, finish, n-1, new_current);

        if var > best_var
            best_var = var;
            best_combination = combination;
        end
    end

    best_thresholds = best_combination;
end

function var = calculate_variance(p, thresholds)
    % 计算给定阈值组合的类间方差
    thresholds = sort([0, thresholds, 256]);
    var = 0;

    for i = 1:length(thresholds)-1
        start = thresholds(i) + 1;
        finish = thresholds(i+1);

        if start > finish
            continue;
        end

        w = sum(p(start:finish));
        if w == 0
            continue;
        end

        mu = sum((start-1:finish-1)' .* p(start:finish)) / w;
        global_mu = sum((0:255)' .* p);
        var = var + w * (mu - global_mu)^2;
    end
end

参考 MATLAB实现图像分割otsuf 源程序代码 www.youwenfan.com/contentalf/23056.html

实际应用示例:细胞图像分割

% 细胞图像分割示例
function cell_segmentation_example()
    % 读取细胞图像
    I = imread('cell_image.png');

    % 转换为灰度图
    if size(I, 3) == 3
        I_gray = rgb2gray(I);
    else
        I_gray = I;
    end

    % 应用高斯滤波去噪
    I_filtered = imgaussfilt(I_gray, 1);

    % 使用Otsu阈值分割
    level = graythresh(I_filtered);
    BW = imbinarize(I_filtered, level);

    % 后处理:去除小对象和填充孔洞
    BW_cleaned = bwareaopen(BW, 50); % 移除面积小于50像素的对象
    BW_cleaned = imfill(BW_cleaned, 'holes'); % 填充孔洞

    % 显示结果
    figure;
    subplot(2, 2, 1);
    imshow(I);
    title('原始细胞图像');

    subplot(2, 2, 2);
    imshow(I_filtered);
    title('滤波后的图像');

    subplot(2, 2, 3);
    imshow(BW);
    title('Otsu分割结果');

    subplot(2, 2, 4);
    imshow(BW_cleaned);
    title('后处理结果');

    % 计算并显示细胞统计信息
    labeled_image = bwlabel(BW_cleaned);
    stats = regionprops(labeled_image, 'Area', 'Centroid');

    % 在图像上标记细胞
    figure;
    imshow(I);
    hold on;
    for i = 1:length(stats)
        text(stats(i).Centroid(1), stats(i).Centroid(2), ...
            num2str(i), 'Color', 'r', 'FontSize', 12, 'FontWeight', 'bold');
    end
    title(['检测到的细胞数量: ', num2str(length(stats))]);
    hold off;

    % 显示细胞面积分布
    areas = [stats.Area];
    figure;
    histogram(areas, 20);
    xlabel('细胞面积 (像素)');
    ylabel('频率');
    title('细胞面积分布');
end

Otsu方法的局限性及改进

虽然Otsu方法在许多情况下表现良好,但它也有一些局限性:

  1. 对噪声敏感:图像中的噪声会影响直方图形状,导致阈值选择不准确
  2. 双峰假设:Otsu方法假设直方图是双峰的,对于单峰或多峰直方图效果可能不佳
  3. 光照不均匀:在光照不均匀的图像中,全局阈值可能不适用

改进方法

% 自适应Otsu阈值处理
function adaptive_otsu_example()
    I = imread('uneven_lighting.jpg');
    I_gray = rgb2gray(I);

    % 全局Otsu阈值
    global_thresh = graythresh(I_gray);
    BW_global = imbinarize(I_gray, global_thresh);

    % 自适应Otsu阈值
    BW_adaptive = imbinarize(I_gray, 'adaptive', ...
        'ForegroundPolarity', 'dark', 'Sensitivity', 0.5);

    % 显示结果比较
    figure;
    subplot(1, 3, 1);
    imshow(I_gray);
    title('原始图像');

    subplot(1, 3, 2);
    imshow(BW_global);
    title('全局Otsu阈值');

    subplot(1, 3, 3);
    imshow(BW_adaptive);
    title('自适应Otsu阈值');
end

总结

Otsu方法是一种简单而有效的自动图像阈值分割技术,特别适用于具有双峰直方图的图像。MATLAB提供了内置函数graythreshimbinarize来简化Otsu阈值分割的实现。对于更复杂的情况,可以考虑使用自适应阈值方法或多阈值Otsu方法。

相关文章
|
机器学习/深度学习 传感器 算法
【交互式阈值二进制图像】采用彩色或单色图像通过交互/手动方式阈值单色图像或彩色图像的单个色带研究(Matlab代码实现)
【交互式阈值二进制图像】采用彩色或单色图像通过交互/手动方式阈值单色图像或彩色图像的单个色带研究(Matlab代码实现)
|
3月前
|
canal 算法 vr&ar
【图像处理】基于电磁学优化算法的多阈值分割算法研究(Matlab代码实现)
【图像处理】基于电磁学优化算法的多阈值分割算法研究(Matlab代码实现)
147 1
|
3月前
|
机器学习/深度学习 资源调度 并行计算
【图像分割】【由局部高斯分布拟合能量驱动的活动轮廓】基于区域的主动轮廓模型,采用变分水平集形式用于图像分割(Matlab代码实现)
【图像分割】【由局部高斯分布拟合能量驱动的活动轮廓】基于区域的主动轮廓模型,采用变分水平集形式用于图像分割(Matlab代码实现)
101 1
|
7月前
|
算法 JavaScript 数据安全/隐私保护
基于GA遗传优化的最优阈值计算认知异构网络(CHN)能量检测算法matlab仿真
本内容介绍了一种基于GA遗传优化的阈值计算方法在认知异构网络(CHN)中的应用。通过Matlab2022a实现算法,完整代码含中文注释与操作视频。能量检测算法用于感知主用户信号,其性能依赖检测阈值。传统固定阈值方法易受噪声影响,而GA算法通过模拟生物进化,在复杂环境中自动优化阈值,提高频谱感知准确性,增强CHN的通信效率与资源利用率。预览效果无水印,核心程序部分展示,适合研究频谱感知与优化算法的学者参考。
|
3月前
|
机器学习/深度学习 算法 调度
【图像分割】视网膜图像分割以提取血管的复杂结构(Matlab代码实现)
【图像分割】视网膜图像分割以提取血管的复杂结构(Matlab代码实现)
|
4月前
|
机器学习/深度学习 并行计算 算法
【图像分割】基于神经气体网络的图像分割与量化(Matlab代码实现)
【图像分割】基于神经气体网络的图像分割与量化(Matlab代码实现)
|
算法 数据挖掘 数据安全/隐私保护
基于FCM模糊聚类算法的图像分割matlab仿真
本项目展示了基于模糊C均值(FCM)算法的图像分割技术。算法运行效果良好,无水印。使用MATLAB 2022a开发,提供完整代码及中文注释,附带操作步骤视频。FCM算法通过隶属度矩阵和聚类中心矩阵实现图像分割,适用于灰度和彩色图像,广泛应用于医学影像、遥感图像等领域。
|
机器学习/深度学习 传感器 算法
【图像去噪】基于自适应小波阈值算法实现图像去噪附matlab源码
【图像去噪】基于自适应小波阈值算法实现图像去噪附matlab源码
|
算法 计算机视觉 索引
基于四叉树的图像分割算法matlab仿真
基于四叉树的图像分割算法matlab仿真
基于四叉树的图像分割算法matlab仿真
|
算法 TensorFlow 算法框架/工具
基于直方图的图像阈值计算和分割算法FPGA实现,包含tb测试文件和MATLAB辅助验证
这是一个关于图像处理的算法实现摘要,主要包括四部分:展示了四张算法运行的效果图;提到了使用的软件版本为VIVADO 2019.2和matlab 2022a;介绍了算法理论,即基于直方图的图像阈值分割,通过灰度直方图分布选取阈值来区分图像区域;并提供了部分Verilog代码,该代码读取图像数据,进行处理,并输出结果到"result.txt"以供MATLAB显示图像分割效果。

热门文章

最新文章