大津算法是将灰度图二值化的常用方法,对具有两个峰的灰度图效果很好。
阈值
t
h
th
th 将图像分为前景像素和背景像素。设整幅图像的平均灰度值为
μ
\mu
μ;前景像素所占的比例为
ω
1
\omega_{1}
ω1,平均灰度值为
μ
1
\mu_{1}
μ1;背景像素所占比例为
ω
2
\omega_{2}
ω2,平均灰度值为
μ
2
\mu_{2}
μ2。则此时的类间方差
σ
2
=
ω
1
(
μ
1
−
μ
)
2
+
ω
2
(
μ
2
−
μ
)
2
\sigma^{2} = \omega_{1}(\mu_1-\mu)^2+ \omega_{2}(\mu_2-\mu)^2
σ2=ω1(μ1−μ)2+ω2(μ2−μ)2
其中
μ
=
ω
1
μ
1
+
ω
2
μ
2
\mu=\omega_1\mu_1+\omega_2\mu_2
μ=ω1μ1+ω2μ2
ω
1
+
ω
2
=
1
\omega_1+\omega_2=1
ω1+ω2=1
整理得:
σ
2
=
ω
1
ω
2
(
μ
1
−
μ
2
)
2
\sigma^{2} = \omega_{1}\omega_{2}(\mu_1-\mu_2)^2
σ2=ω1ω2(μ1−μ2)2
接下来就是要遍历
t
h
th
th找到最大的类间方差
σ
2
\sigma^2
σ2,那么此时的
t
h
th
th就是我们要找的二值化阈值。
matlab代码如下所示:
% 读取图像
I = imread('ccc.jpg');
% 初始化灰度直方图
H = zeros(256);
% 计算灰度直方图
[l, w] = size(I);
for r = 1:l
for c = 1:w
index = I(r, c) + 1;
H(index) = H(index) + 1;
end
end
% 显示灰度直方图
figure;
hist = bar(0:255, H, 'histc');
max = 0;
% 阈值
index = 0;
sum = 0;
for j = 1:256
sum = sum + j * H(j);
end
n_pixels = l * w;
n_current_pixels = 0;
average_gray_value = 0;
% 寻找最大类间方差
for i = 1:255
gray_value = i * H(i) + average_gray_value * n_current_pixels ;
n_current_pixels = n_current_pixels + H(i);
average_gray_value = gray_value / n_current_pixels;
average_gray_value2 = (sum-gray_value)/(n_pixels - n_current_pixels)
s = n_current_pixels * (n_pixels - n_current_pixels) / n_pixels^2 * (average_gray_value-average_gray_value2)^2;
if (s > max)
max = s;
index = i;
end
end
th = index
I2 = zeros(size(I));
I2 (find(I>=th)) = 255;
I2 (find(I<th)) = 0;
figure;
imshow(I2)
测试结果:
输入图像
输出图像
OTSU-method可视化: