实验 改进的KMeans算法实现车牌字符的分割.docx
- 文档编号:9627919
- 上传时间:2023-02-05
- 格式:DOCX
- 页数:17
- 大小:84.83KB
实验 改进的KMeans算法实现车牌字符的分割.docx
《实验 改进的KMeans算法实现车牌字符的分割.docx》由会员分享,可在线阅读,更多相关《实验 改进的KMeans算法实现车牌字符的分割.docx(17页珍藏版)》请在冰豆网上搜索。
实验改进的KMeans算法实现车牌字符的分割
实验改进的K-Means算法实现车牌字符的分割
车牌识别的一般过程:
车牌定位--->字符分割--->字符识别。
本实验实现了前两步。
车牌定位从大体上分为两种,基于灰度和基于底纹,本程序结合了以上两种方法实现了车牌精确定位,即先基于灰度图像得到一个大概的位置,然后再根据底纹实现精确定位。
不失一般性,本人设计了只针对蓝底白字(车牌有四种:
蓝底白字、黑底白字、白底黑字、黄底黑字)的车牌设计了算法,现实中,蓝底白字占了车牌的绝大多数。
字符分割是本实验的重点。
车牌分割有很多方法,如神经网络算法、水平投影、点阵结构等。
因为车牌识别要求是实时,要求具有很快的响应速度。
所以字符分割这一步对车牌字符的最终识别和整个程序运行效率有很重要的影响,本实验基于K-Means聚类算法思想实现了字符分割,因为车牌规定是7位的,所以K取7。
另外本实验对K-Means算法进行了改进,充分考虑了初始点的设置及迭代结束条件。
实验结果证明这种改进的K-Means算法实现车牌字符分割是快速、有效的。
整个算法用VC++6.0实现。
一、实验目的
(1)掌握图像数据挖掘的基本方法
(2)K-Means聚类算法完成车牌字符分割(重点)
二、实验内容
基本功能要求:
(1)实现车牌的精确定位
(2)对K-Means聚类算法进行改进,即如何进行初始点和迭代条件的确定,快速完成车牌字符分割。
三、算法设计
本算法分为二部分,车牌定位和字符分割。
车牌定位的各个函数、算法思想是图像处理和模式识别课程中重要讨论的内容,这里只作了简单介绍。
本实验着重讨论如何基于K-MEANS算法思想实现车牌字符分割。
程序执行流程如下:
1、车牌定位
(1)读取车牌图片
用OnBmpopen()函数实现
(2)车牌定位的各函数说明
车牌的定位由一系列函数完成,各函数说明如下:
OnRgbtogray();//彩色转成灰度
为了降低计算复杂度,一般将彩色转换为灰度,公式:
gray=0.3*red+0.59*green+0.11*blue(数字图像处理岗萨雷斯)
Onjunhenghua();//均衡化
为了增强图像对比,采用了均衡化操作(图像工程(上)章毓晋)
OnBianYuanJianChe();//边缘检测
此函数利用了Sobel算子检测车牌和字符的边缘(数字图像处理岗萨雷斯)。
因为粗略定位需要是根据这些边缘来定位的。
OnEzbz();//二值化
用数组记录图片的可能区域
OnHxqy();//粗略定位,给出候选区域
根据记录的信息完成车牌的粗略定位,之所以说是“粗略”是因为车牌周围的点是车牌识别的噪音,所以根据车牌的边缘来实现精确定位是很难的。
OnQyqd();//基于纹理定位
根据上一步的结果,得到了车牌的大概位置,再根据车牌的底色为蓝色(对于其它三种情况分类判断即可,本实验只针对蓝色底纹)这一特点,可以实现车牌的精确定位。
判别条件如下:
hl=2*b-r-g>80r表示像素的红色分量,g表示绿色分量,b表示蓝色分量(这里的80是根据不断实验得出的阀值)
2、K-Means聚类算法实现车牌字符分割
改进的K-Means算法实现步骤:
Step1每个字符代表一个类。
因为车牌有7个字符(如图所示)组成,故设置7个聚类中心,
为了能在较少的次数下收敛,对K-Means进行了改进,即类的初始点不是随机选取,而是根据车牌的特点取值,如:
对于车牌字符横坐标:
oldposition[0][0]=left+width/12;//第一个字符位置离车牌左边约1/12*车牌宽度
oldposition[i][0]=oldposition[i-1][0]+2*width/15;//后一个字符离前一个字符约1/15宽度
对于车牌字符纵坐标
oldposition[i][1]=bottom+height/2;//每一个车牌的纵坐标大约是车牌高度的一半
这样设置的理由:
由于车牌的像素坐标都是整数,所以坐标用整型变量,这大大提高了算法执行效率。
以上设置保证了初始点在各类内,如图所示:
红点代表初始点的大概位置,这样设置初始点后,只要经过几次迭代就会收敛。
即中心会移到各字符的中心位置。
Step2扫描所有字符像素,按照距离最近原则,对车牌像素进行归类:
d=(x-oldposition[i][0])2+(y-oldposition[i][1])2
公式中x,y是当前扫描的像素坐标,oldposition[i][0],oldposition[i][1]是聚类中心的x,y坐标,离i类中心坐标最近,就把该像素归到i类,本程序用不同的颜色表示不同的类,如国所示的最后分类结果:
Step3完成一次归类后,重新计算各类中心坐标:
newposition[i][0]=∑xi/n;
newposition[i][1]=∑yi/n;
计算:
di=|newposition[i][0]-oldposition[i][0]|+|newposition[i][1]-oldposition[i][1]|
D=∑di(i=0,……6)
判断D<=e?
若不小于,将新的类中心坐标作为类中心,返回Step2;否则结束。
程序中取e=3,也即它们之间的距离差的平均值小于0.5(3/7取整)时,迭代结束。
”e”取3的理由:
由于每个像素的坐标都是整型的,它们的坐标相差最小值是1个像素点,所以只要保证新类的中心和上次类中心距离差平均小于0.5,就说明找到各类中心,即分割成功。
字符分割算法流程:
四、实验结果分析
1、实验的输入与输出
运行程序(VC++6.0):
双击KmeansDealBmp.exe--->单击“打开图像”-->选“测试图片”文件夹中的一幅图片--->单击车牌字符分割处理中的“车牌定位”--->“K—means”分割字符。
测试1:
(一种颜色代表一种分类)
测试2:
2、实验的结果分析
本人找了20幅有代表性的蓝底白字车牌进行了测试,效果如下:
图片序号
识别效果
K-Means分割效果
迭代次数
1
优
优
2
2
优
优
3
3
差
优
2
4
优
优
2
5
差
差
9
6
优
良
2
7
良
良
3
8
优
优
2
9
优
优
3
10
优
优
2
11
优
优
2
12
差
差
4
13
优
良
2
14
优
优
3
15
优
优
2
16
优
优
3
17
差
差
7
18
优
良
2
19
优
良
2
20
优
优
3
(优:
表示完全可以作下一次的字符识别操作
如:
良:
表示需要作适当的处理(如残点补缺)才作为下一次的字符识别操作
如:
“粤”字有残缺;
差:
表示完全不能识别出来
如:
“粤”和“A”是同一种颜色
)
实验结果的几点说明:
(1)车牌定位效果差时,分割效果也差,而且迭代次数明显增大,主要是K—Means算法对噪音敏感
如:
只能分割出第5,6,7位字符
(2)平均迭代次数=3说明算法是快速的。
原因:
都是基于整型运算,并且初始点的设置离中心点较近。
(3)分割成功率约90%,只要定位足够好,能去掉车牌周围的噪声,这个比例完全可以提高。
(4)基于本实验的K—Means聚类分割结果,如再用模板匹配法或其它方法,可识别出字符。
即可完成车牌识别的最后一步---字符识别。
五、关键代码说明(全部源码用VC++6.0打开工程文件即可)
一、车牌定位的源代码:
voidCBmpDisplayView:
:
OnCldw()
{
OnRgbtogray();//彩色转成灰度
Onjunhenghua();//均衡化
OnBianYuanJianChe();//边缘检测
OnEzbz();//二值化
OnHxqy();//检测候选区域
OnQyqd();//候选区域定位
OnJqdw();//基于纹理定位
}
二、K--Means均值算法的源代码
voidCBmpDisplayView:
:
OnJlfg()//K--Means均值分类算法实现,k为7
{
intwidth,height,Dibwidth;
BYTE*p_data,b,g,r;
CBmpDisplayDoc*pDoc=GetDocument();
ASSERT_VALID(pDoc);
p_data=pDoc->ylpBuf;//图像在内存中的开始位置
height=pDoc->bi.biHeight;//图像高度
width=pDoc->bi.biWidth;//图像宽度
Dibwidth=pDoc->Dibwidth;//每一行图像像素
LPBYTEtemp=newBYTE[height*Dibwidth];
memcpy(temp,p_data,height*Dibwidth);
intleft=pDoc->newLbpx;//车牌左下角x坐标
intbottom=pDoc->newLbpy;//车牌左下角y坐标
width=pDoc->newLbl;//车牌宽度
height=pDoc->newLbh;//车牌高度
intoldposition[7][2];//上一次聚类中心
intnewposition[7][2];//归类后的聚类中心
intclasscount[7];//每类的像素个数,
intdt[7];
intdl=0;
intcount=0;
for(inti=bottom;i for(intj=left;j { b=temp[i*Dibwidth+j*3]; g=temp[i*Dibwidth+j*3+1]; r=temp[i*Dibwidth+j*3+2]; dl=2*b-r-g; if((dl>20)||((b-g)>20))//2*b-r-g>20或者b-g>20是深蓝色车牌 temp[i*Dibwidth+j*3]=temp[i*Dibwidth+j*3+1]=temp[i*Dibwidth+j*3+2]=0;//去掉底色 else { temp[i*Dibwidth+j*3]=temp[i*Dibwidth+j*3+1]=temp[i*Dibwidth+j*3+2]=255; count++; } } if(count==0)//如果不是深蓝色,则|g-r|>60为浅蓝色 { for(inti=bottom;i for(intj=left;j { b=temp[i*Dibwidth+j*3]; g=temp[i*Dibwidth+j*3+1]; r=temp[i*Dibwidth+j*3+2]; intaveragecolor=(b+g+r)/3; if(abs(g-r)>60)//|g-r|>60为浅蓝色 temp[i*Dibwidth+j*3]=temp[i*Dibwidth+j*3+1]=temp[i*Dibwidth+j*3+2]=255;//去掉底色 else { temp[i*Dibwidth+j*3]=temp[i*Dibwidth+j*3+1]=temp[i*Dibwidth+j*3+2]=0; count++; } } } //以下设置7个初始点坐标 oldposition[0][0]=left+width/12; oldposition[1][0]=oldposition[0][0]+width/6; oldposition[2][0]=oldposition[1][0]+width/6; for(i=3;i<7;i++) oldposition[i][0]=oldposition[i-1][0]+2*width/15; for(i=0;i<7;i++) oldposition[i][1]=bottom+height/2; //各变量赋初值 intd=0; intnl=0; inte=3;//收敛条件 diedai=1;//迭代次数 intflag=1; while(flag)//迭代开始 { for(intk=0;k<7;k++) classcount[k]=0;//各类像素开始赋初值 for(k=0;k<7;k++)//新类中心坐标赋初值 { newposition[k][0]=0; newposition[k][1]=0; } for(i=bottom;i for(intj=left;j { if(temp[i*Dibwidth+j*3]! =0) { for(intk=0;k<7;k++) dt[k]=(oldposition[k][0]-j)*(oldposition[k][0]-j) +(oldposition[k][1]-i)*(oldposition[k][1]-i);//计算当前点与每个类的中心距离 d=dt[0]; nl=0; for(k=1;k<7;k++)//找最小值 if(d>dt[k]) { d=dt[k]; nl=k; } switch(nl)//离nl类最近 {//以下先求出每类中心的坐标矢量和及及统计不同分类的像素个数,并用不同颜色表示 case0: newposition[0][0]=newposition[0][0]+j;//第1类中的x坐标矢量和 newposition[0][1]=newposition[0][1]+i;//∑第1类中的y坐标矢量和 classcount[0]++;//第1类中的像素个数 temp[i*Dibwidth+j*3]=1;//蓝色分量赋值 temp[i*Dibwidth+j*3+1]=1;//绿色分量赋值 temp[i*Dibwidth+j*3+2]=255;//红色分量赋值 break; case1: newposition[1][0]=newposition[1][0]+j; newposition[1][1]=newposition[1][1]+i; classcount[1]++; temp[i*Dibwidth+j*3]=255; temp[i*Dibwidth+j*3+1]=125; temp[i*Dibwidth+j*3+2]=0; break; case2: newposition[2][0]=newposition[2][0]+j; newposition[2][1]=newposition[2][1]+i; classcount[2]++; temp[i*Dibwidth+j*3]=255; temp[i*Dibwidth+j*3+1]=125; temp[i*Dibwidth+j*3+2]=255; break; case3: newposition[3][0]=newposition[3][0]+j; newposition[3][1]=newposition[3][1]+i; classcount[3]++; temp[i*Dibwidth+j*3]=125; temp[i*Dibwidth+j*3+1]=125; temp[i*Dibwidth+j*3+2]=255; break; case4: newposition[4][0]=newposition[4][0]+j; newposition[4][1]=newposition[4][1]+i; classcount[4]++; temp[i*Dibwidth+j*3]=255; temp[i*Dibwidth+j*3+1]=255; temp[i*Dibwidth+j*3+2]=0; break; case5: newposition[5][0]=newposition[5][0]+j; newposition[5][1]=newposition[5][1]+i; classcount[5]++; temp[i*Dibwidth+j*3]=255; temp[i*Dibwidth+j*3+1]=0; temp[i*Dibwidth+j*3+2]=125; break; case6: newposition[6][0]=newposition[6][0]+j; newposition[6][1]=newposition[6][1]+i; classcount[6]++; temp[i*Dibwidth+j*3]=255; temp[i*Dibwidth+j*3+1]=0; temp[i*Dibwidth+j*3+2]=255; break; } } } for(intt=0;t<7;t++)//求各类新的中心坐标 { if(classcount[t]==0) classcount[t]=1; newposition[t][0]=newposition[t][0]/classcount[t];//x坐标的矢量和除以矢量个数 newposition[t][1]=newposition[t][1]/classcount[t];//y坐标的矢量和除以矢量个数 } intsubd=0; for(t=0;t<7;t++) { intdt=abs(newposition[t][0]-oldposition[t][0]) +abs(newposition[t][1]-oldposition[t][1]);//求t类新的中心点与初始点中心的差距 subd=subd+dt;//∑dt } if(subd<=e)//迭代结束条件 flag=0; else { for(t=0;t<7;t++) { //用新的坐标作为类的中心 oldposition[t][0]=newposition[t][0]; oldposition[t][1]=newposition[t][1]; } diedai++; } } //显示聚类效果 pDoc->zlpBuf=temp; pDoc->zflag=1; pDoc->cflag=1; } 精品文档考试教学资料施工组织设计方案
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 实验 改进的KMeans算法实现车牌字符的分割 改进 KMeans 算法 实现 车牌 字符 分割
![提示](https://static.bdocx.com/images/bang_tan.gif)