基于FPGA水平垂直投影法(字符分割)的实现 作者:OpenS_Lee 1 背景知识 图像对应方向的投影,就是在该方向取一条直线,统计垂直于该直线(轴)的图像上的像素的黑点数量,累加求和作为该轴该位置的值;基于图像投影的切割就是将图像映射成这种特征后,基于这种特征判定图像的切割位置(坐标),用这个坐标来切割原图像,得到目标图像。 1.1 OTSU算法 OTSU算法是由日本学者OTSU于1979年提出的一种对图像进行二值化的高效算法。最大类间方差法是由日本学者大津于1979年提出的,是一种自适应的阈值确定的方法,又叫大津法,简称OTSU。它是按图像的灰度特性,将图像分成背景和目标2部分。背景和目标之间的类间方差越大,说明构成图像的2部分的差别越大,当部分目标错分为背景或部分背景错分为目标都会导致2部分差别变小。因此,使类间方差最大的分割意味着错分概率最小。对于图像I(x,y),前景(即目标)和背景的分割阈值记作T,属于前景的像素点数占整幅图像的比例记为ω0,其平均灰度μ0;背景像素点数占整幅图像的比例为ω1,其平均灰度为μ1。图像的总平均灰度记为μ,类间方差记为g。假设图像的背景较暗,并且图像的大小为M×N,图像中像素的灰度值小于阈值T的像素个数记作N0,像素灰度大于阈值T的像素个数记作N1,则有:
ω0=N0/ M×N---------------------------------------------------- (1)
ω1=N1/ M×N ----------------------------------------------------(2)
N0+N1=M×N---------------------------------------------------- (3)
ω0+ω1=1 -------------------------------------------------------- (4)
μ=ω0*μ0+ω1*μ1------------------------------------------------ (5)
g=ω0(μ0-μ)^2+ω1(μ1-μ)^2----------------------------------- (6)
将式(5)代入式(6),得到等价公式: g=ω0ω1(μ0-μ1)^2----------------(7)
采用遍历的方法得到使类间方差最大的阈值T,即为所求。 Otsu算法步骤如下: 设图象包含L个灰度级(0,1…,L-1),灰度值为i的的象素点数为Ni ,图象总的象素点数为N=N0+N1+...+N(L-1)。灰度值为i的点的概为:P(i) = N(i)/N.门限t将整幅图象分为暗区c1和亮区c2两类,则类间方差σ是t的函数:σ=a1*a2(u1-u2)^2 式中,aj 为类cj的面积与图象总面积之比,a1 = sum(P(i)) i->t, a2 = 1-a1; uj为类cj的均值,u1 = sum(i*P(i))/a1 0->t, u2 = sum(i*P(i))/a2, t+1->L-1 该法选择最佳门限t^ 使类间方差最大,即:令Δu=u1-u2,σb = max{a1(t)*a2(t)Δu^2}。 1.2水平垂直投影 水平投影是指二维图像按列向x 轴方向投影垂直投影是指二维图象按行向y 轴方向投影投影的结果可以看成是一维图像. 2 matlab实现 要实现一幅图像的字符分割,首先我们要将图像转换成灰度图像,然后采用大津法(OTSU,自适应阈值分割)找出最佳的阈值分割点,将灰度图像转化为二值图像,最后利用水平垂直投影法找出字符与字符之间的边界点。 graythresh(image)函数输入是一副图像,在我做的图像的变化检测方向就是输入差异图(两幅图像对应位置做差或者做比,或者做对数比),输出就是阈值。在这个函数中,是使用最大类间方差法找到图片的一个合适的阈值(threshold)。再利用im2bw(将灰度图像转换为二值图像)函数,将找到的阈值输入,就可以把原图变为一个二值图。 matlab源代码: I=imread('2.bmp'); gray=rgb2gray(I); level = graythresh(gray); %OTSU bw=im2bw(gray,level); b = ~bw; [m n]=size(b); y = 1:n; x = 1:m; figure subplot(221),imshow(b); title('bw image'); subplot(222),plot(sum(b,2),x); title('水平投影'); subplot(223),plot(y,sum(b)); title('垂直投影'); subplot(224),imshow(I); title('original drawing'); 图1 数字图像目标的水平垂直投影 如图1所示,采用matlab对2行5列数字图像进行水平垂直投影,垂直投影图显示了5个起伏不一的波峰,波峰的上升点和下降点既是数字的左右边界。水平投影类似,波峰的上升点和下降点既是数字的上下边界。由上下左右边界点即可分割出每个数字。 图2 车牌的水平垂直投影 如图2 所示,我们对车牌进行了水平和垂直投影,依然可以通过水平垂直投影来分割出每个特征目标,这为车牌识别提供了很好的帮助,分割出每一个字符最后对每个字符进行识别。 3 基于FPGA实现水平垂直投影法进行字符分割 图3 基于FPGA的水平垂直投影模块 如图3所示,我们在TFT_CTL模块后端对rgb图像首先进行了rgb2ycbcr算法的实现,然后将灰度图像转化为二值图像,最后在二值图像的基础上对图像进行了水平和垂直投影,最终完成了多个字符的分割。这为FPGA实现车牌识别打下了良好的基础。 垂直投影模块: 图4 水平垂直投影模块
图5 水平垂直投影实验原图 如图4和以上代码所示,我只实现了1行3列的水平垂直投影,如果需要实现更多的字符分割可以在以上代码添加修改就可以实现更多目标字符的分割。 FPGA的水平垂直投影与matlab的水平垂直投影过程类似。FPGA的阈值分割没有使用otsu法形成二值图像。采用测试环境自我判断选取阈值,程序如下: 对于水平垂直投影测试线显示程序: 图6 垂直投影分割三个字符效果图 利用水平和垂直投影完成字符分割程序: 图7 水平垂直投影实现两个字符的边界分割 图8 水平垂直投影实现三个字符的边界分割 如图7,8所示,采用水平垂直投影最终完成了多个数字的上下左右边界的寻找和分割出了每个独立字符。这我后期我们的FPGA实现车牌识别提供了便利。 欢迎大家关注我的微信公众号:FPGA开源工作室
|