大津算法

在计算机视觉和图像处理领域,大津二值化法(Otsu's method)是由命名的一种用于自动图像阈值分割的方法。 该方法用于对基于聚类的图像进行二值化,即将一个灰度图像转化为二值图像。算法假定图像根据双模直方图(前景像素和背景像素)包含两类像素,并计算出能将这两类像素分开的最佳阈值,使得类内方差最小,或等效地,类间方差最大。
因此,大津二值化法是一种一维离散的費舍爾判别分析的类似方法,与相关,并且等同于在强度直方图上执行的全局最优k-means算法。
原始论文中还描述了多级阈值扩展方法, 并且后来提出了计算效率高的实现方法。

方法
在大津算法中,我们穷举搜索能使类内方差最小的阈值,定义为两个类的方差的加权和:

:\sigma^2_w(t)=\omega_1(t)\sigma^2_1(t)+\omega_2(t)\sigma^2_2(t)
权重 \omega_i 是被阈值 t 分开的两个类的概率,而 \sigma^2_ i 是这两个类的方差。

大津证明了最小化类内方差和最大化类间方差是相同的:

算法

计算每个强度级的直方图和概率

设置 \omega_i(0) 和 \mu_i(0) 的初始值

遍历所有可能的阈值 t = 1 \ldots 最大强度

更新 \omega_i 和 \mu_i

计算 \sigma^2_b(t)

所需的阈值对应于最大的 \sigma^2_b(t)

你可以计算两个最大值(和两个对应的)。\sigma^2_{b1}(t) 是最大值而 \sigma^2_{b2}(t) 是更大的或相等的最大值

所需的阈值 = \frac{\text{threshold}_1 + \text{threshold}_2 }{2}

JavaScript实现
注:输入参数total是给定图像中的像素数。输入参数histogram是灰度图像不同灰度级(典型的8位图像)的256元直方图。此函数输出图像的阈值。

function otsu(histogram, total) {
var sum = 0;
for (var i = 1; i = max ) {
threshold1 = i;
if ( between > max ) {
threshold2 = i;
}
max = between;
}
}
return ( threshold1 + threshold2 ) / 2.0;
}

C实现
unsigned char otsu_threshold( int* histogram, int pixel_total )
{
unsigned int sumB = 0;
unsigned int sum1 = 0;
float wB = 0.0f;
float wF = 0.0f;
float mF = 0.0f;
float max_var = 0.0f;
float inter_var = 0.0f;
unsigned char threshold = 0;
unsigned short index_histo = 0;

for ( index_histo = 1; index_histo = max_var )
{
threshold = index_histo;
max_var = inter_var;
}
}

return threshold;
}

MATLAB实现
total为给定图像中的像素数。
histogramCounts为灰度图像不同灰度级(典型的8位图像)的256元直方图。
level为图像的阈值(double)。

function level = otsu(histogramCounts, total)
%% OTSU automatic thresholding method
sumB = 0;
wB = 0;
maximum = 0.0;
threshold1 = 0.0;
threshold2 = 0.0;
sum1 = sum((1:256).*histogramCounts.'); % the above code is replace with this single line
for ii=1:256
wB = wB + histogramCounts(ii);
if (wB == 0)
continue;
end
wF = total - wB;
if (wF == 0)
break;
end
sumB = sumB + ii * histogramCounts(ii);
mB = sumB / wB;
mF = (sum1 - sumB) / wF;
between = wB wF (mB - mF) * (mB - mF);
if ( between >= maximum )
threshold1 = ii;
if ( between > maximum )
threshold2 = ii;
end
maximum = between;
end
end
level = (threshold1 + threshold2 )/(2);
end

另一种方法是用向量化方法(可以很容易地转换为便于GPU处理Python矩阵数组版本)

function [threshold_otsu] = Thredsholding_Otsu( Image)
%Intuition:
%(1)pixels are divided into two groups
%(2)pixels within each group are very similar to each other
% Parameters:
% t : threshold
% r : pixel value ranging from 1 to 255
% q_L, q_H : the number of lower and higher group respectively
% sigma : group variance
% miu : group mean
% Author: Lei Wang
% Date : 22/09/2013
% References : Wikepedia,
% for multi children Otsu method, please visit : https://drive.google.com/file/d/0BxbR2jt9XyxteF9fZ0NDQ0dKQkU/view?usp=sharing
% This is my original work

nbins = 256;
counts = imhist(Image,nbins);
p = counts / sum(counts);

for t = 1 : nbins
q_L = sum(p(1 : t));
q_H = sum(p(t + 1 : end));
miu_L = sum(p(1 : t) .* (1 : t)') / q_L;
miu_H = sum(p(t + 1 : end) .* (t + 1 : nbins)') / q_H;
sigma_b(t) = q_L q_H (miu_L - miu_H)^2;
end

[~,threshold_otsu] = max(sigma_b(:));
end

该实现有一点点冗余的计算。但由于大津算法快速,这个实现版本是可以接受,并且易于理解的。因为在一些环境中,如果使用向量化的形式,可以更快地运算循环。大津二值化法使用架构最小的堆-孩子标签(heap-children label)可以很容易地转变成多线程的方法。

参考文献
外部链接

评论 (0)

  • 还没有评论,来抢沙发吧。