Niblack二值化方法的实现

本文介绍了一种基于局部阈值的图像分割方法——Niblack算法,并通过实例展示了其在文本图像处理中的应用效果。

申明,本文非笔者原创,原文转载自:http://www.cnblogs.com/nani/archive/2012/12/12/2814324.html

最近一直在研究图像分割技术,越研究觉得越有意思。这里所说的研究其实也只是研究别人论文然后自己实现一下而已罢了。。。

图像分割就是把图像中的各个部分分开,能区分出哪里是前景,哪里是背景,如果前景和背景分别用0和1表示,那就是叫做图像二值化了。但是图像分割也不仅仅限于二分,可以任意多的分。从这个角度讲二值化是图像分割结果的一种表示而已,只不过二分研究的比较多,也比较容易些。

至于分割的方法有很多种,比较粗的分类可以分为全局和局部的。全局方法就是一个阈值,像素值大于此值的为1,小于此值的为0。局部方法就是对每一个像素求阈值。Niblack方法就是局部方法中的一种,它根据以像素点为中心的邻域内的点的情况为此像素计算阈值。下面是每个像素阈值的计算公式,m是方差,s是标准差。

 

 

 

 

 

 

看起来还是比较简单的,下面是实现这个算法的matlab代码:

 

function g=segNiBlack(f,w2,k)
% segmentation method using  Niblack thresholding method
% input: w2 is  the half width of the window
 
w = 2*w2 + 1;
window = ones(w, w);
% compute sum of pixels in  WxW window
sp = conv2(f, window, 'same' );
% convert to mean
n = w^2;            % number of pixels in  window
m = sp / n;
% compute the std
if  k ~= 0
     % compute sum of pixels squared in  WxW window
     sp2 = conv2(f.^2, window, 'same' );
     % convert to std
     var  = (n*sp2 - sp.^2) / n / (n-1);
     s = sqrt( var ); 
     % compute Niblack threshold
     t = m + k * s;
else
     t = m;
end
g=f<t;
 
end

函数的输入f是要二值化的图像,w2是窗口大小的一半,k就是系数。代码里面的conv2是卷积,将图像矩阵与全1矩阵做卷积,其实就是再求这个窗口内像素的和。这样做速度比较快,比一个像素一个像素的遍历速度快10多倍。

Niblack还算是一种比较常用的二值化算法,算法简明,速度较快,效果也不错,经常用在文本图像的文字与背景分割中。下面就拿我用手机照纸上的一些文字,测试一下。

左:用手机照的一篇打印的论文中的文字  右:用Niblack算法进行文本分离的结果

可以看到背景有些噪点,文字有些地方连了起来,但是整体效果还不错,为了取得更好的结果,通常预处理和后续处理是必不可少的环节。看起来有点模糊的是因为图片太大为了放到文章里我给它缩小了一下。

代码和参数如下:

tf=imread('http://www.cnblogs.com/mydb/tests/paperwords.jpg');
tf=rgb2gray(tf);
tf=double(tf);
tf=medfilt2(tf,[5,5]);
gb2=segNiBlack(tf,32,0.01);
gb2=medfilt2(gb2,[7,7]);
figure();imshow(gb2);



Niblack二值化算法是比较简单的局部阈值方法,阈值的计算公式是T = m + k*v,其中m为以该像素点为中心的区域的平均灰度值,v是该区域的标准差,k是一个系数,matlab程序如下:

[c-sharp]  view plain copy
  1. I = imread('card3.bmp');  
  2. I = rgb2gray(I);  
  3.   
  4. w =  2;%     
  5. max = 0;     
  6. min = 0;     
  7. [m,n] = size(I);     
  8. T = zeros(m ,n );     
  9.     
  10. %  
  11. for i = (w + 1):(m - w)     
  12.     for j = (w + 1):(n - w)        
  13.         sum = 0;  
  14.         for k = -w:w     
  15.             for l = -w:w     
  16.                 sum = sum + uint32(I(i + k,j + l));  
  17.             end     
  18.         end     
  19.         average = double(sum) /((2*w+1)*(2*w+1));  
  20.         s = 0;  
  21.         for k = -w:w     
  22.             for l = -w:w     
  23.                 s = s +   (uint32(I(i + k,j + l)) - average)*(uint32(I(i + k,j + l)) - average);  
  24.             end     
  25.         end     
  26.         s= sqrt(double(s)/((2*w+1)*(2*w+1)));  
  27.           
  28.         T(i,j) = average + 0.2*s;  
  29.     end     
  30. end     
  31. for i =  1:m   
  32.     for j = 1:n   
  33.         if I(i,j) > T(i,j)     
  34.             I(i,j) = uint8(255);     
  35.         else    
  36.             I(i,j) = uint8(0);     
  37.         end     
  38.     end     
  39. end     
  40. imshow(I);    

上述程序中选择的窗口大小是5*5,处理结果不好,产生了大量的噪声...


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值