1 otsu方法参考我的另一篇博文: OTSU算法学习 OTSU公式证明
2 sauvola方法, 参考我的另一篇博文: sauvola二值化算法研究
3 Bersen方法
Bersen方法感觉有些粗糙, 只是考虑目标点附近区域的像素灰度值的最大值和最小值, 阈值是最大值和最小值的均值.下面是它的matlab实现,出自这篇博文【二值化】Bernsen算法.如果用C语言实现要用积分图的方法.
%局部阈值操作Bersen算法 clc clear I = imread(‘card8.bmp‘); w =1;%矩阵大小为2*w+1 T =0;%阈值大小 max =0; min =0; [m,n]= size(I); T = zeros(m -2*w,n -2*w); %根据bersen算法计算每个像素点的阈值 for i =(w +1):(m - w) for j =(w +1):(n - w) max = uint8(I(i,j)); min = uint8(I(i,j)); for k =-w:w for l =-w:w if max < uint8(I(i + k,j + l)) max = uint8(I(i + k,j + l)); end if min > uint8(I(i + k,j + l)) min = uint8(I(i + k,j + l)); end end end T(i,j)=0.5*(max + min); end end for i =(w +1):(m - w) for j =(w +1):(n - w) if I(i,j)> T(i,j) I(i,j)= uint8(255); else I(i,j)= uint8(0); end end end imshow(I); |
下图是这个方法的效果
上图中对于图像右侧的效果很差.
4 niblack算法
Niblack二值化算法是比较简单的局部阈值方法,阈值的计算公式是T = m + k*v,其中m为以该像素点为中心的区域的平均灰度值,v是该区域的标准差,k是一个系数. sauvola二值化算法的计算公式是T = mean*(1 + k*((std / 128) - 1)). Niblack和sauvola方法类似.下面贴matlab实现的代码和效果图.不做进一步分析了.
I = imread(‘2.bmp‘); %I = rgb2gray(I); w = 2;% max =0; min =0; [m,n]= size(I); T = zeros(m ,n ); % for i =(w +1):(m - w) for j =(w +1):(n - w) sum =0; for k =-w:w for l =-w:w sum = sum + uint32(I(i + k,j + l)); end end average = double(sum)/((2*w+1)*(2*w+1)); s =0; for k =-w:w for l =-w:w s = s + (uint32(I(i + k,j + l))- average)*(uint32(I(i + k,j + l))- average); end end s= sqrt(double(s)/((2*w+1)*(2*w+1))); T(i,j)= average +0.2*s; end end for i = 1:m for j =1:n if I(i,j)> T(i,j) I(i,j)= uint8(255); else I(i,j)= uint8(0); end end end imshow(I); |
5 循环阈值算法
代码的实现和k均值聚类算法类似,但是累积值在循环中没有清空,具体原因不知道.只是把代码贴和效果到下面.
clc clear I = imread(‘2.bmp‘); %I = rgb2gray(G); %l = rgb2gray(h);%转换成灰度图像,得到灰度值 %imhist(img);%得到灰度直方图 %disp(img);%显示各像素的灰度值 %循环阈值选择方法 gray1 =0;%一部分图像的灰度值之和 gray2 =0;%另一部分图像的灰度值之和 u1 =0;%一部分图像的平均灰度值 u2 =0;%另一部分的平均灰度值 k =0;%一部分图像的像素个数 r =0;%另一部分图像的像素个数 x =0;%阈值和 T =0;%图像的阈值 [m,n]= size(I)%获取图像大小 %获取平均阈值 for i =1:m for j =1:n x = x + uint32(I(i,j)); end end T = x/(m*n);%初始阈值 T1 =0; while T ~= T1 T1 = T; for i =1:m for j =1:n if I(i,j)< T gray1 = gray1 + uint32(I(i,j)); k = k +1; else gray2 = gray2 + uint32(I(i,j)); r = r +1; end end end u1 = gray1/k; u2 = gray2/r; T =(u1 + u2)/2;%新的阈值 end %BW = im2bw(g,T);%转换成二值图像 T %输出最后选择的阈值 %显示区域,把不在阈值范围内的点的灰度值置为255 for i =1:m for j =1:n if I(i,j)> T I(i,j)= uint32(255); else I(i,j)= uint32(0); end end end %se = strel(‘disk‘,1); %h = imclose(I,se); %h = imdilate(I,se); %y = imerode(h,se); %h = medfilt2(I,[3,3]; %imshow(y); imshow(I); |
总结: 实际应用中实现上首先要用积分图技术来实现提速,其次要综合考虑全局阈值方法和局部阈值方法,以全局阈值为基础,考虑局部均值,二值化等.这个局部不能太小,太小了就会有噪点.
本文参考了博文图像二值化算法总结,这里感谢cxf7394373.