%利用大津法(Ostu)计算阈值
%{
大津法由大津于1979年提出,对图像Image,记t为前景与背景的分割阈值,前景点数占图像
比例为w0,平均灰度为u0;背景点数占图像比例为w1,平均灰度为u1。
图像的总平均灰度为:u=w0*u0+w1*u1。从最小灰度值到最大灰度值遍历t,
当t使得值g=w0*(u0-u)2+w1*(u1-u)2 最大时t即为分割的最佳阈值。
对大津法可作如下理解:该式实际上就是类间方差值,阈值t分割出的前景和背景两部分构成
了整幅图像,而前景取值u0,概率为 w0,背景取值u1,概率为w1,总均值为u,根据方差的
定义即得该式。因方差是灰度分布均匀性的一种度量,方差值越大,说明构成图像的两部分差
别越大, 当部分目标错分为背景或部分背景错分为目标都会导致两部分差别变小,因此使类
间方差最大的分割意味着错分概率最小。
%}
%Matlab实现大津法计算阀值
function threshold = Otsu(grayImage)
%取出最大灰度值,max只能找到每一列的最大值
maxGrayValue = max(max(grayImage));
%取出最小灰度值
minGrayValue = min(min(grayImage));
%求初始阀值
t = double(minGrayValue:maxGrayValue);
%图像大小
gsize = size(grayImage);
%图像像素总个数
muxsize = gsize(1)*gsize(2);
for k = 1:length(t)
%从最小灰度值到最大值的计算方法
tk = t(1,k);
%定义前景和背景像素数
iforeground = 0;
ibackground = 0;
%定义前景和背景的灰度总和
foreground = 0;
background = 0;
for i = 1:gsize(1)
for j = 1:gsize(2)
tmp = grayImage(i,j);
if(tmp >= tk)
%前景灰度值
iforeground = iforeground + 1;
foreground = foreground + double(tmp);
else
%背景灰度值
ibackground = ibackground + 1;
background = background + double(tmp);
end
end
end
w0 = iforeground / muxsize;
w1 = ibackground / muxsize;
u0 = foreground / iforeground;
u1 = background / ibackground;
t(2,k) = w0*w1*(u0-u1)*(u0-u1);
end
%遍历后寻找grayIamge的第二行的最大值
%第二行方差的最大值,忽略NaN
omax = max(t(2,:));
%方差最大值所对应的列号,find只能检查一行中的数,或一维数组
index = find(t(2,:) >= omax);
%从第一行取出灰度值作为阀值
t = t(1,index);
threshold = t;
%清理窗口
close all
clear all
clc
%读取图像
img_name = input('请输入图像名字:','s');
I = imread(img_name);
J = I;
%第一次色彩空间变换
h = rgb2hsv(J);
%获得图像大小
[m n] = size(J(:,:,1));
%将变换后的图像的HSV值规范至[0,255]范围内
for i = 1:m
for j = 1:n
for k = 1:3
J(i,j,k) = int8(255*h(i,j,k));
end
end
end
%第二次色彩空间变换
h=rgb2hsv(J);
%再次将变换后的图像的HSV值规范至[0,255]范围内
for i = 1:m
for j = 1:n
for k = 1:3
J(i,j,k) = int8(255*h(i,j,k));
end
end
end
%将RGB图像转化为灰度图像
gray = J(:,:,1);
%利用Otsu阈值检测法取图像二值化阈值
t = Otsu(gray);
%根据阈值将图像二值化
for i = 1:m
for j = 1:n
if gray(i,j) < t
gray(i,j) = 255;
else
gray(i,j) = 0;
end
end
end
%利用闭运算去除噪声
bim=im2bw(gray);
SE=strel('arbitrary',eye(5));
BW2=imclose(bim,SE);
%显示原始图像
imshow(I);
title('原始图像');
%最终结果
figure,imshow(BW2);
title('阴影检测结果');
%清理窗口
close all
clear all
clc
%读取图像
img_name = input('请输入图像名字:','s');
I = imread(img_name);
J = I;
%第一次色彩空间变换
h = rgb2hsv(J);
%获得图像大小
[m n] = size(J(:,:,1));
%将变换后的图像的HSV值规范至[0,255]范围内
for i = 1:m
for j = 1:n
for k = 1:3
J(i,j,k) = int8(255*h(i,j,k));
end
end
end
%第二次色彩空间变换
h=rgb2hsv(J);
%再次将变换后的图像的HSV值规范至[0,255]范围内
for i = 1:m
for j = 1:n
for k = 1:3
J(i,j,k) = int8(255*h(i,j,k));
end
end
end
%将RGB图像转化为灰度图像
gray = J(:,:,1);
%利用Otsu阈值检测法取图像二值化阈值
t = Otsu(gray);
%根据阈值将图像二值化
for i = 1:m
for j = 1:n
if gray(i,j) < t
gray(i,j) = 255;
else
gray(i,j) = 0;
end
end
end
%利用闭运算去除噪声
bim=im2bw(gray);
SE=strel('arbitrary',eye(5));
BW2=imclose(bim,SE);
%显示原始图像
imshow(I);
title('原始图像');
%最终结果
figure,imshow(BW2);
title('阴影检测结果');