@shaobaobaoer
2018-10-27T15:26:44.000000Z
字数 3540
阅读 7128
matlab
数字图像处理
************************************************************************
> File Name: 《数字图像处理》实验九 MATLAB 阈值分割算法
> Author: 罗天涵
> Student-Id: 16121141
> Mail: luotianhan@126.com
************************************************************************
参考文章
http://www.cnblogs.com/wangduo/p/5556903.html
Prewitt 等人于六十年代中期提出的直方图双峰法(也称 mode 法) 这是一个典型的全局单阈值分割方法。该方法的基本思想是:
假设图像中有明显的目标和背景,则其灰度直方图呈双峰分布,当灰度级直方图具有双峰特性时,选取两峰之间的谷对应的灰度级作为阈值。如果背景的灰度值在整个图像中可以合理地看作为恒定,而且所有物体与背景都具有几乎相同的对比度,那么,选择一个正确的、固定的全局阈值会有较好的效果。
function [outputArg1] = function_mode_threshold_segmentation(inputArg1,inputArg2)
I=inputArg1;
I = rgb2gray(I);
% figure;imhist(I);
%人工选定阈值进行分割,选择阈值为 input2
[width,height]=size(I);
T1=inputArg2;
for i=1:width
for j=1:height
if(I(i,j)<T1)
BW1(i,j)=0;
else
BW1(i,j)=1;
end
end
end
outputArg1 = BW1;
end
相比较双峰图,免去了人工输入。能够得出一个最好的参数。并且能够快速收敛,又能够在每一个迭代过程中,新产生的阈值优于上一次的阈值。
1.统计图像灰度直方图,求出图象的最大灰度值和最小灰度值,分别记为ZMAX和ZMIN,令初始阈值T0=(ZMAX+ZMIN)/2;
2. 根据阈值TK将图象分割为前景和背景,计算小于TO所有灰度的均值ZO,和大于TO的所有灰度的均值ZB。
3. 求出新阈值TK+1=(ZO+ZB)/2;
4. 若TK==TK+1,则所得即为阈值;否则转2,迭代计算。
function [outputArg1,outputArg2] = function_iteration_threshold_segmentagion(inputArg1)
% inputArg1 灰度图像 gray
% output 二值化图像
f=inputArg1;
f=im2double(f);
T=0.5*(min(f(:))+max(f(:)));
done=false;
count=255;
while ~done
g=f>=T;
Tn=0.5*(mean(f(g))+mean(f(~g))); % 备注 mean(f(g)) 是取 f 中所有像素大于 T 的均值
done=abs(T-Tn)<0.1; % 当最后的T-Tn小于 0.1的时候表示循环结束。可以设置的更加精确些
T=Tn;
count=count-1;
if (count <= 0) % 设置最大迭代次数为 255
'Exception Max Iteration Depth'
done = 1;
end
end
r=im2bw(f,T);
outputArg1 = r;
end
有时候物体和背景的对比度在图像中不是处处一样的,普通阈值分割难以起作用。这时候可以根据图像的局部特征分别采用不同的阈值进行分割。只要我们将图像分为几个区域,分别选择阈值,或动态地根据一定邻域范围选择每点处的阈值,从而进行图像分割。
日本学者大津在1979年提出的自适应阈值确定方法。 按照图像的灰度特性,将图像分为背景和目标两部分。背景和目标之间的类间方差越大,说明构成图像的2部分的差别越大,当部分目标错分为背景或部分背景错分为目标都会导致2部分差别变小。因此,使类间方差最大的分割意味着错分概率最小。
对于图像I(x,y),前景(即目标)和背景的分割阈值记作T, 属于前景的像素点数占整幅图像的比例记为ω0,其平均灰度μ0;背景像素点数占整幅图像的比例为ω1,其平均灰度为μ1。图像的总平均灰度记为μ,类间方差记为g。
假设图像的背景较暗,并且图像的大小为M×N,
图像中像素的灰度值小于阈值T的像素个数记作N0,像素灰度大于阈值T的像素个数记作N1,则有:
将 5 和 6 相互结合,就可以化间得到:
简单而言,大津算法就是找到一个T让两个区域的方差最大
function [outputArg1] = function_OTSU_threshold_segmentation(inputArg1)
% inputArg1 图像 gray
% outputArg1 = inputArg1;
f = inputArg1;
[M,N] = size(f);
T = 0;
result_T = 0;
gmax = 0;
while (T<=255)
g=f>=T;
w0 = numel(f(g))/(M*N);
w1 = numel(f(~g))/(M*N);
p0 = mean(f(g));
p1 = mean(f(~g));
% w0 + w1 = 1
% numel(f(g)) + numel(f(~g)) = M * N
%Tn=0.5*(mean(f(g))+mean(f(~g))); % 备注 mean(f(g)) 是取 f 中所有像素大于 T 的均值
tmp = (w0 * w1) * (p0 - p1)^2;
if (tmp > gmax)
gmax = tmp;
result_T =T;
end
T = T+1;
end
outputArg1 = im2bw(f,result_T/255);
end
把图像分成m*n块子图,求取每一块子图的灰度均值就是所有像素灰度值之和除以像素点的数量,这个均值就是阈值了。这种方法明显不比大津法好,因为均值法和大津法都是从图像整体来考虑阈值的,但是大津法找了一个类间方差最大值来求出最佳阈值的;这两种方法子图越多应该分割效果会好一点,但效率可能会变慢。这个算法很蠢,但也是一种思路
function [outputArg1] = function_average_threshlod_segmentation(inputArg1)
% inputArg1 image gray
f = inputArg1;
T = mean(mean(f));
outputArg1 = im2bw(f,T/255);
end
以上我们实现了四种算法。当然,双峰法的T值是自己定义的。这个方法就不参与比较了。
function test_function_threshlod_segmentation(inputArg1)
%UNTITLED9 此处显示有关此函数的摘要
% 此处显示详细说明
f = inputArg1;
if isa(f,'rgb')
f = rgb2gray(f);
end
I1 = f;
I2 = function_iteration_threshold_segmentagion(f);
I3 = function_OTSU_threshold_segmentation(f);
I4 = function_average_threshlod_segmentation(f);
figure;% 开一个新的图像区域
subplot(2, 2, 1); imshow(I1); title('原图像');
subplot(2, 2, 2); imshow(I2, []); title('迭代阈值分割图像');
subplot(2, 2, 3); imshow(I3, []); title('大津法阈值分割图像');
subplot(2, 2, 4); imshow(I4, []); title('均值法阈值分割图像');
grid on
end
原图像
测试结果
原图像
测试结果
备注,我将最后生成的内容反色了。可以看到这里的均值阈值分割更加优秀一些。
原图像
测试结果
在此,能够看出均值阈值分割算法比前两者明显差上一筹。