不均匀光照文本图像的二值化。
因为文本图像的背景是不均匀的,所以想先求出图片的亮度背景,用原图减去背景,就会得出文本的内容,再进行二值化,可能就会得到我们想要的结果。
以下是详细的处理过程:
首先要估算出原始图片的背景图。
图片中某一点的背景,可以用该点w*w邻域内较亮的点的集合来进行估算。就好比一张白纸,一个区域内最白的一些点就可以代表该区域的背景。
我们逐行逐列的扫描图像,依次选取每个像素点w*w邻域内亮度最高的六个点。为了减少白噪声像点对背景的影响,我们去掉这六个点中最大的,对其余的五个点求平均值,认为这个平均值就是该点的背景值。
以下为matlab实现:
I = imread('C:\test.bmp');
I = rgb2gray(I);
%colfilt(I,[31 31],'sliding',@bk)
% 功能:以列方法进行邻域处理,也可执行常规非线性滤波。
% 用法:B = colfilt(A,[m n],block_type,fun)
% 该函数生成了一幅图像A,在A中,每一列对应于其中心位于图像内某个位置的邻域所包围的像素。然后将函数应用于该矩阵中。
% [m n]表示大小为m行n列的邻域。block_type表示了一个字符串,包括'distinct','sliding'两种,
% 其中'sliding'是在输入图像中逐个像素地滑动该m乘n的区域。fun表示引用了一个函数进行处理,
% 函数返回值的大小必须和原图像大小相同。
I2 = uint8(colfilt(I,[31 31],'sliding',@bk));
function v=bk(x)
N = size(x);
b = sort(x);
nMax = b((N(1)-47) : (N(1)-1),:);
v = mean(nMax);
end
想要去掉不均匀的光照背景,可以简单理解为,原图减去背景图。
但是,可想而知,背景区域颜色越深的话,该区域背景与所要显示的文本之间的对比度就会越小。
所以,要根据背景颜色的深浅,来对对比度进行补偿。
k的值为连续分段的线性函数,其物理意义是对比度放大的倍数。
可以简单理解为,背景颜色越深,k值越大。也就是背景颜色值越小,k值越大,对比度所需要放大的倍数越大。
matlab实现如下:
% 对背景暗区与背景亮区的对比度进行补偿
I3 = minusBk(I,I2);
function v=minusBk(A,B)
F = 255;
ret = A;
[m,n] = size(A);
for i=1 : m
for j=1 : n
k = setK(B(i,j));
if B(i,j) > A(i,j)
ret(i,j) = F - k*(B(i,j)-A(i,j));
if ret(i,j) < 0.75*F
ret(i,j) = 0.75*F;
end
else
ret(i,j) = F;
end
end
end
v=ret;
end
% get k
function v=setK(e)
if e < 20
k = 2.5;
elseif e>=20 && e<=100
k = 1 + ((2.5-1)*(100-e))/80;
elseif e>100 && e<200
k = 1;
else
k = 1 + (e-220)/35;
end
v = k;
end
对比度补偿之后的结果
matlab实现Sauvola二值化:
I4 = uint8(colfilt(I3,[31 31],'sliding',@sauvola));
function v=sauvola(x)
Y=128;
m1= mean(x);
v2 = double(x(481,:));
s = size(v2);
s1=(1-0.15*(1-std(double(x))/Y));
v3=v2;
for i = 1:s(2)
if (v2(1,i)>m1(1,i)*s1(1,i))
v3(1,i)=255;
else
v3(1,i)=0;
end
end
v = v3;
end
实验结果还算满意。但是有的文本部分显示的还是不好,感觉是由于邻域的选取问题,邻域选的小,该邻域内笔画过多,导致邻域内的亮度平均值过低,低于实际的背景。从而导致的二值化结果异常。
调大了二值化时选取的邻域,解决了上面的问题,但是对图像边缘部分的二值化,还是处理的有问题
参考文献:
①不均匀光照文本图像的二值化 贺志明
②基于光照不均匀图像的自适应二值化方法研究 郭佳