车牌字符分割
车牌的定位与字符分割 报告
车牌的定位与分割实验报告一实验目的针对交通智能系统所拍摄的汽车图片,利用设定的算法流程,完成对汽车车牌部分的定位,分割车牌部分,并完成字符的分割,以便于系统的后续分析及处理。
二实验原理详见《车牌的定位与字符分割》论文。
三概述1一般流程车牌自动识别技术大体可分为四个步骤:图像预处理、车牌定位与分割、车牌字符的分割和车牌字符识别。
而这四个步骤又可归结为两大部分:车牌分割和车牌字符识别。
图1-1为车牌自动识别技术的一般流程图。
2本实验的流程(1)图像预处理:图像去噪(2)车牌的定位:垂直边缘检测(多次)形态学处理的粗定位合并邻近区域结合车牌先验知识的精确定位(3)车牌预处理:车牌直方图均衡化倾斜校正判定(蓝底白字或者黄底黑字)归一化、二值化(4)字符的分割:垂直投影取分割阈值确定各个字符的左右界限(结合字符宽度、间隔等先验知识)分割字符四实验过程4.1图像预处理4.1.1图像去噪一般的去噪方法有:空间域上的均值滤波和中值滤波;频率域上的巴特沃斯滤波器。
图4-1是各滤波器处理椒盐噪声的效果。
a.被椒盐噪声污染的图片 b.均值滤波的效果图 c.中值滤波的效果图 d.BLPF的效果图图4-1 各滤波器处理椒盐噪声的仿真可见,中值滤波对椒盐噪声的处理效果极好,而一般所拍摄的图片上最多的便是孤立的污点,所以此处以中值滤波为主进行去噪。
图4-2是采用中值滤波处理实际汽车图片的效果。
a.原始图像b.灰度图像c.中值滤波后的图像图4-2 中值滤波处理实际汽车图片的效果很显然,经过中值滤波后去除了原图上的部分污点。
4.1.2图像复原由于通常情况下都不知道点扩展函数,所以我们采用基于盲解卷积的图像复原策略。
图4-3~4-7图是函数进行盲解卷积的实验结果,其中图4-3是图像cameraman 的模糊图像。
图4-3 模糊图像在盲解卷积处理中,选择适当大小的矩阵对恢复图像的效果很重要。
PSF的大小比PSF的值更重要,所以首先指定一个有代表性的全1矩阵作为初始PSF。
【车牌识别】-车牌中字符分割代码详解
【车牌识别】-车牌中字符分割代码详解车牌识别项⽬中,关于字符分割的实现:思路: 1. 读取图⽚,使⽤ cv2 。
2. 将 BGR 图像转为灰度图,使⽤ cv2.cvtColor( img,cv2.COLOR_RGB2GRAY) 函数。
3. 车牌原图尺⼨(170, 722) ,使⽤阈值处理灰度图,将像素值⼤于175的像素点的像素设置为 255 ,不⼤于175的像素点的像素设置为0 。
4.观察车牌中字符,可以看到每个字符块中的每列像素值的和都不为 0 ,这⾥做了假设,将左右结构的省份简写的字也看作是由连续相邻的列组成的,如 “ 桂 ” 。
5. 对于经过阈值处理的车牌中的字符进⾏按列求像素值的和,如果⼀列像素值的和为 0,则表明该列不含有字符为空⽩区域。
反之,则该列属于字符中的⼀列。
判断直到⼜出现⼀列像素点的值的和为0,则这这两列中间的列构成⼀个字符,保存到字典character_dict 中,字典的 key 值为第⼏个字符 ( 下标从0开始 ),字典的value值为起始列的下标和终⽌列的下标。
character_dict 是字典,每⼀个元素中的value 是⼀个列表记录了夹住⼀个字符的起始列下标和终⽌列下标。
6. 之后再对字符进⾏填充,填充为170*170⼤⼩的灰度图(第三个字符为⼀个点,不需要处理,跳过即可。
有可能列数不⾜170,这影响不⼤)。
7. 对填充之后的字符进⾏resize,处理成20*20的灰度图,然后对字符分别进⾏存储。
代码实现:1### 对车牌图⽚进⾏处理,分割出车牌中的每⼀个字符并保存2# 在本地读取图⽚的时候,如果路径中包含中⽂,会导致读取失败。
34import cv25import paddle6import numpy as np7import matplotlib.pyplot as plt8#以下两⾏实现了在plt画图时,可以输出中⽂字符9 plt.rcParams['font.sans-serif']=['SimHei']10 plt.rcParams['axes.unicode_minus'] = False111213# cv2.imread() 读进来直接是BGR 格式数据,数值范围在 0~255 。
车牌字符分割算法研究
1 绪论1.1 背景介绍为了实现车牌字符识别,通常要经过车牌位置检测、车牌字符分割和字符识别三个关键步骤。
车牌位置检测是根据车牌字符目标区域的特点,寻找出最符合车牌特征的区域。
车牌字符分割就是在车牌图像中找出所有字符的上下左右边界,进而分割出每个车牌字符。
在实际应用中,车牌字符分割的效果对车牌字符识别正确率会产生很大的影响,由于车牌图像亮度不均、尺度变化、透视失真、字符不完整等因素,使图像质量存在较大差异,进而影响图像分割的效果,因此车牌字符分割这一技术仍然具有很大的研究意义。
在实际的监控场景中,车牌图像的透视失真通常是由于拍摄视角的变化或车辆位置的移动,相机光轴偏离车牌平面的法线方向造成的。
由于车牌图像在整幅图像中占有较小的比例,所以车牌图像几何校正主要工作是校正车牌图像的旋转和剪切失真。
旋转投影法和直线拟合法是两种主要的偏斜校正方法。
旋转投影法是为了获取垂直倾斜角,即将车牌图像穷举逐个角度进行剪切变换,然后统计垂直投影数值为0的点数,得到最大值对应的角度。
这种方法受背景区域的干扰比较大。
另一种方法是直线拟合车牌字符的左边界点从而获得垂直倾斜角,该方法为直线拟合法。
该方法并没有逐个角度对车牌图像进行剪切变换,从左边界点拟合出的直线通常不能真正用来代表车牌的垂直倾斜方向,检测出的角度存在较大误差,且字符左侧噪声对角度检测干扰太大,鲁棒性较差。
因此找到一种更准确和迅速的车牌垂直倾斜矫正方法是十分重要的。
通过得到最小的字符投影点坐标方差,得到另一种车牌垂直矫正方法。
首先将车牌字符图像进行水平校正,根据字符的区域的上下边界,将车牌字符进行粗分割。
然后将剪切变换后的字符点进行垂直偷用。
当得到投影点最想左边方差时,便能导出两类剪切角闭合表达是,最后便是确定垂直投影的倾斜角并对此进行校正。
投影法是目前最常用的车牌分割算法之一,其算法简单并且计算复杂度低。
该方法的核心思想是将车牌图像进行水平投影和垂直投影,利用峰谷特征来定位车牌字符的上下左右边界。
车牌识别中的号码分割方法
车牌识别中的号码分割方法刘聪074301027车牌拍照自动识别技术是实现车辆身份自动识别的一种途径。
是近年来计算机视觉与模式识别技术在智能交通领域应用的重要研究课题之一。
因为车辆牌照号码和车辆是一一对应的,如同居民身份证和每个公民的关系一样,因此车辆牌照字符自动识别系统可用于一切需要对车辆进行管理的场合,比如公路收费站、停车场、十字路口等交通关卡等处,对于道路交通、园区和停车场车辆管理具有巨大的经济价值和现实意义。
车牌识别方法可以分为3个部分:车牌定位;车牌字符分割;车牌字符识别.这3部分紧密相关,每一步的输出都将作为下一步处理的输入,因此每一步的精确度都直接影响下一步的工作,从而影响车牌识别的最终结果。
首先要输入原始图像,从原始图像中确定车牌的相对位置,,完成对车牌的倾斜度校正;从提取的图像中切分出单个字符;最后输出车牌号码的字符串。
其中车牌字符的正确分割是进行下一步车牌字符识别的基础,目前常用的方法有如下几种:(1)车牌区域纹理特征的方法。
这种方法是利用车牌区域字符和底色具有不同的灰度特征从而进行边框去除和字符分割的方法。
(2)基于数学形态学的方法。
利用形态学的腐蚀和膨胀,将车牌字符区域组成连通域的方法去除边框,再进一步采用字符连通域的形式进行字符切分。
(3)基于Hough变换的字符分割方法。
还有人完全利用Hough变换,寻找车牌字符的上下边界,再结合车牌字符的排列特征进行字符的分割。
在得到一个或几个车牌区域后,先将其分割为单个的字符,然后进行单个字符的识别.传统的方法是使用投影法进行分割.先统计定位出的车牌区域的直方图,然后将统计值等于。
的几列中的一列作为分割的界限.这种分割方法实现起来比较简单,但是适应性很差,在预处理效果不好的情况下,很难有满足条件的列.而为了获取满足传统方法的条件,只有增加预处理的条件.因此,处理完后的图像不可避免地损失一部分有用信息,为进一步的处理造成不必要的困难,还可能引入额外误差.并且,在车牌倾斜的角度比较大或被拍摄车牌上的字符比较密集时,投影的方法从本质上失去了意义.为了避免上述两种弊端,采用一种新方法分割单个字符.该方法既可从一定程度上消除了预处理效果较差带来的影响,又可从根本上解决了倾斜车牌分割的间题.为了说明该方法的效果,使用了一个有较大倾斜角度的车牌做试验,如图3所示.首先,按照上一个步骤中精确定位车牌位置的方法,确定各个连通区域,去掉矩形区域中一些不可能是字符区域部分,例如宽度过大(约大于1/7车牌)或是连通区域中像素的个过少的区域,然后做出剩余各个连通区域的外接矩形,选取高和宽比值最为接近的4个连通区域,如图d所示.通过研究发现,车牌在正常或倾斜的情况下,(这种倾斜的情况包括车牌本身倾斜或由于拍摄的角度造成的倾斜),车牌上各个字符的顶点实际上是在一条直线上,而大部分的数字、字母的结构是上下、左右基本对称的,所以各个数字和字母的中心也基本在一条直线上.因此,依据各连通区域的信息拟合一条直线可以取各连通区域的中点,也可以取各连通区域的最高和最低点拟合这条直线,在多数情况下,能够得到较好的拟合效果.利用拟合出的1条或2条直线,就能够比较准确地确定车牌上字符的上下边界.图c中所示的2条直线就是利用字符的上边缘和下边缘拟合出来的.假设拟合的直线斜率为k,则所有字符的外接矩形与这条直线的相交角度是相同的.从图d中的4个矩形中任意选取一个,将其假定为字符的大小,然后将这个矩形沿斜率为k的直线来回运动,按照车牌字符分布的特点,这个矩形框应该可以包含每一个字符.由此可提取每一个字符,因为如果将汉字看作连通区域,1个汉字则是由几个连通区域组成,而这个矩形框恰好可以将这些连通区域包含在内.并且像1这个高和宽的比值与其他的字符不同的数字,也能借助拟合的直线解决这一问题.本系统并未对倾斜的字符进行矫正,因为经研究发现,车牌上的字符因倾斜会产生一定程度的变形,但是这种变形并非是在二维空间上产生的.因此对其进行矫正仍有一定的困难.所以,对于倾斜字符的识别,可以通过在下一步中加大训练集解决.。
车牌识别系统功能和参数
车牌识别系统功能和参数车牌识别系统是一种用于自动识别和识别出车辆号牌的技术。
它利用计算机视觉和模式识别的原理和技术,通过图像处理和特征提取等方法,从输入的图像中提取车牌号码并进行识别。
车牌识别系统主要可以分为图像采集、车牌定位、字符分割、字符识别和车牌识别五大模块。
首先,车牌识别系统的功能包括图像采集、车牌定位、字符分割、字符识别和车牌识别等。
通过图像采集模块,可以采集到来自摄像头或其他图像输入设备的车辆图像。
车牌定位模块可以对车辆图像进行处理,找出图像中的车牌位置。
字符分割模块可以将车牌图像中的字符进行分割,从而得到单个字符图像。
字符识别模块使用OCR(光学字符识别)技术,对字符进行识别,并将字符的识别结果输出。
最后,车牌识别模块通过将字符的识别结果进行组合,得到完整的车牌号码,并输出识别结果。
1.图像采集参数:包括图像分辨率、拍摄角度、曝光度、对比度等。
合理的图像采集参数可以保证车牌在图像中的清晰可见性,减少图像中的噪声和干扰。
2.车牌定位参数:包括车牌的位置、大小、高度、宽度等。
通过调整车牌定位参数,可以准确地找到车牌在图像中的位置,排除其他干扰因素。
3.字符分割参数:包括字符之间的间距、字符的大小、字符的高度、宽度等。
合适的字符分割参数可以确保字符之间的距离和大小符合标准,并准确地划分字符。
4.字符识别参数:包括字符模板库、字符识别算法、识别率等。
良好的字符识别参数可以提高字符识别的准确度和速度。
5.车牌识别参数:包括车牌识别算法、车牌号码格式、识别结果输出等。
优化的车牌识别参数可以保证系统对各种车牌号码的识别正确率,快速地输出识别结果。
除了以上几个参数之外,还有一些额外的参数可以用于进一步优化系统的性能,如图像预处理参数、特征提取参数、分类器参数等。
这些参数的选择和调整可以根据实际应用需求和系统性能要求进行调整。
总之,车牌识别系统的功能和参数都是为了实现车牌号码的自动识别和识别而设计的。
利用反馈的车牌字符分割算法
Ke w r s y o d
Lc n epa h rc r e m na o I a epe po es g P o c o F e b c D srt c s et n f ma o i s l ec aat g e t in m g r —rcsi r e t n e d a k e t es t n j i i e oi r s r t n c e n a o i
李文举 姜周恩 朱正强 崔晓松
( 辽宁师范大学计算 机与信息技术学 院 辽宁 大连 16 8 ) 10 1
摘
要
字符 分 割是 车 牌 识 别 系 统 的重 要 步 骤 。 提 出一 种 利 用 反 馈 的 车 牌 字 符 分 割 算 法 。 首 先 , 车 牌 图像 进 行 预 处 理 ; 次 , 对 其
c r c e s Th is e e ha a t r . e fr t l v l ̄ e a k i h e d c a e n c r c e s c u n he wi h o i g e c r c e t e s c nd l v lf e b c s db c s t e f e ba k b s d o ha a t r ’ o nta d t dt f s n l ha a t r,h e o e e e d a k i
u e o o g e me tt n o e c aa t r o h lt ;i al ,w — v lfe b c s e l y d t o d c n e me tt n o e p ae s d f rr u h s g na i ft h r c es n t e pa e f l t o l e e d a k i mp o e o c n u tf e s g n ai ft lt o h n y e i o h
常用的车牌识别算法
常用的车牌识别算法包括以下几种:
1. 车牌定位算法:用于确定车辆图像中车牌的位置。
这种算法通常会使用图像处理技术,如梯度信息投影统计、小波变换、车牌区域扫描连线算法等,以识别图像中的车牌区域。
2. 字符分割算法:在车牌定位后,需要将车牌中的字符进行分割。
这种算法通常会使用图像处理技术和机器学习算法,如基于深度学习的字符分割算法,以准确地将各个字符分割开来。
3. 字符识别算法:用于识别分割后的字符。
这种算法通常会使用机器学习算法,如卷积神经网络(CNN)或循环神经网络(RNN),以对字符进行分类和识别。
4. 神经网络识别算法:大规模神经网络识别算法是一种深度学习算法,它能够同时处理车牌定位和字符识别两个任务,具有更高的准确性和鲁棒性。
5. 启发式车牌定位算法:综合利用了图像处理技术和机器学习算法,以提高车牌定位的准确性。
这种算法通常会使用一些特征选择方法,如SVM、HOG等,以将车牌区域和非车牌区域进行区分。
6. 角度偏差和光照波动控制算法:在车牌定位和字符识别过程中,车辆的角度偏差和光照波动会影响算法的准确性。
这种算法通常会使用一些图像处理技术,如滤波、归一化等,以减小这些因素的影响。
这些算法在车牌识别过程中相互配合,以实现准确的车牌识别。
车牌识别系统中车牌定位与字符分割的研究
车牌识别系统中车牌定位与字符分割的研究一、本文概述随着科技的发展和智能交通系统的普及,车牌识别系统已经成为了现代交通管理的重要组成部分。
车牌识别系统的核心在于准确、快速地实现车牌的定位与字符分割。
本文旨在深入探讨车牌识别系统中车牌定位与字符分割的关键技术,并分析其在实际应用中的挑战与解决方案。
本文将对车牌识别系统的基本框架进行概述,介绍车牌定位与字符分割在其中的地位和作用。
接着,本文将详细阐述车牌定位技术的发展历程和现状,包括基于颜色、纹理、形状等特征的定位方法,以及近年来兴起的深度学习技术在车牌定位中的应用。
同时,本文还将对字符分割技术的研究现状进行梳理,包括基于投影分析、边缘检测、形态学处理等方法的字符分割算法。
在此基础上,本文将重点分析车牌定位与字符分割在实际应用中面临的挑战,如复杂背景下的车牌定位不准确、字符粘连或断裂导致的分割失败等问题。
针对这些问题,本文将提出相应的解决方案,如通过改进算法提高定位精度、采用多特征融合的方法提高字符分割的鲁棒性等。
本文将通过实验验证所提方法的有效性,并对实验结果进行分析和讨论。
本文还将展望车牌识别系统的未来发展趋势,探讨新技术在车牌定位与字符分割中的应用前景。
通过本文的研究,旨在为车牌识别系统的优化和改进提供有益的参考和借鉴。
二、车牌定位技术研究车牌定位技术是车牌识别系统的关键环节,它涉及从复杂的背景中准确提取出车牌区域。
随着计算机视觉和图像处理技术的不断发展,车牌定位技术也取得了显著的进步。
早期的车牌定位主要基于车牌的颜色和边缘特征。
由于中国车牌通常为蓝底白字,因此可以通过颜色过滤来初步提取出可能的车牌区域。
随后,利用边缘检测算法(如Canny边缘检测)来进一步细化车牌的轮廓,从而实现车牌的粗定位。
然而,这种方法受光照条件、车牌污损等因素影响较大,定位准确性有待提高。
为了克服颜色和边缘特征方法的局限性,研究人员开始尝试基于纹理和形状特征的车牌定位方法。
结合垂直投影法与固定边界分割的车牌字符分割算法(附源码和详细解析)
结合垂直投影法与固定边界分割的车牌字符分割算法(附源码和详细解析)上⼀篇博⽂简单有效的车牌定位算法(附源码和详细解析),详细介绍了数学形态学处理车牌粗定位与蓝⾊像素统计、⾏列扫描的车牌精确定位算法。
没有看的朋友可以先看上⼀篇博⽂。
这次,在牌照字符的分割上,我结合了⽬前使⽤最多的投影法和车牌固定边界的多阈值分割算法。
它的⼤致实现过程如下:第⼀步先对上⼀节粗定位完牌照的只有⿊⽩两⾊的图像bg2实施伪彩⾊标记。
第⼆步获取标记区域各连通块的尺⼨参数,⽤作下⼀步遍历的索引。
第三步投影得直⽅图,取⼀个分割阈值,划分出背景和字符的范围,也就是在直⽅图histrow(histcol)中区分⾕底点和上升点。
第四步分析峰⾕,得到例如最⼤峰中⼼距等参数。
最后⼀步,根据上⼀步求得的参数分割字符。
具体分割流程图如下图:图5-1 字符分割流程图⼀、车牌区域彩⾊标记与特征提取 对粗定位车牌后的⼆值图像作连通区域4邻域的伪彩⾊标记的⽬的是为了⽅便计算出车牌区域的⾯积、宽⾼度以及车牌框架的⼤⼩、区域开始和结束的⾏列位置等区域特征参数,是为后续的车牌投影分析操作作预准备。
在这⼀步骤中,⾸先以4领域⼤⼩为模块对⼆值图像作区域标记,给每块连通区域块标记上序数,获取图像中连通区域的块数和图像矩阵L,初步计算出各连通区域的框架⼤⼩,然后再根据车牌的先验知识设置亮度⾼度的合理阈值筛选出真正车牌区域的连通域,记录下该连通域的序数,最后对车牌区域块作区域特征提取,获取车牌的框架⼤⼩、宽⾼度、宽⾼⽐例以及开始位置点的⾏、列数等参数。
在MATLAB中对车牌号码为粤A6ZC93和粤AC609Z两车辆的车牌粗定位⼆值图像作伪彩⾊标记效果如下图:(a)粤A6ZC93 (b)粤AC609Z图5-2 区域标记与特征参数提取⼆、车牌预处理(1) 基于Radon变换的倾斜校正 从车体侧⾯拍摄的车辆图像中提取出来的牌照会出现⾓度的倾斜,为了后续操作的⽅便,需要进⾏⾓度的校正。
汽车牌照字符分割的自适应算法
汽车牌照字符分割的自适应算法摘要:本文提出一种针对汽车牌照字符分割的自适应算法。
该算法首先对获取的彩色车牌图像进行灰度化、灰度拉伸、边缘检测、Hough变换、旋转变换、二值化等一系列处理,以突出车牌文字、矫正车牌位置;然后对预处理结果的水平投影进行削峰填谷操作,以获得车牌字符的上下边界,再对上下边界内子图像的垂直投影进行削峰填谷操作,以获得车牌每个字符的左右边界,进而最终确定车牌每个字符的具体位置。
实验结果表明该方法字符分割准确、运算速度快、适应能力强,有很好的实用性。
关键词:牌照字符分割削峰填谷自适应边缘检测1 引言汽车牌照识别是智能交通中的重要课题之一,它广泛应用于电子收费、车流监控、高速公路收费系统等领域,是交通科技发展与研究的热点问题之一。
从外部获取汽车的前部或后部图像后,车牌识别主要分三大部分:1)车牌定位;2)车牌字符分割;3)车牌字符识别。
其中车牌字符分割处在承前启后的关键位置,字符分割的准确率与速度直接关系到整个系统运行的成败。
对于车牌字符分割的方法,国内外相关专家、学者经过多年的研究,积累了大量成功的经验。
国外关于车牌字符分割比较有代表性的算法如文献[1~2]的方法等,国内对车牌字符分割的研究也取得了很大进展,如文献[3~4]的方法等。
总的看来,车牌字符分割的方法划分为基于颜色特征的聚类方法和投影分割两大类。
基于颜色特征进行聚类在理想情况下是可行的,但实际车牌由于污损等原因,使车牌文字及背景颜色局部改变,而且车牌背景与文字颜色也有数种搭配等,使得基于颜色特征聚类分割字符的效果不够理想;而投影分割方法是比较直观有效的方法,得到广泛应用,但也有几个关键问题需要解决,如字符倾斜、车牌边框剔除、铆钉的处理、尤其是字符边界处理等。
本文即是针对以上问题,从实际应用的角度出发,提出一种基于削峰填谷[5]的自适应算法,该算法充分利用车牌文字颜色与背景颜色的差异进行优化的二值化处理,利用车牌文字排列及文字规格特征进行字符分割,简化操作步骤,动态获取阈值,对存储空间进行动态管理,从时间和空间两个方面进行优化,取得了较好的效果。
车牌识别系统的原理
车牌识别系统的原理
车牌识别系统的原理可以简要概括为以下几个步骤:图像获取、车牌定位、字符分割、字符识别和结果输出。
首先,系统需要获取车辆的图像,可以通过摄像头、监控摄像机等设备实现。
接下来,车牌定位是识别的第一步,它的目的是在整个图像中找到车牌的位置。
通常使用图像处理的技术,如边缘检测、颜色分析等来实现车牌定位。
定位到车牌后,需要进行字符分割。
字符分割是指将车牌图像中的字符分离出来,使得每个字符都可以单独进行识别。
字符分割是一个相对复杂的任务,常用的方法有基于像素点、基于边缘、基于投影等方法。
字符分割完成后,就可以进行字符识别。
字符识别是整个车牌识别系统中最核心的步骤。
常见的方法有基于模板匹配、基于神经网络、基于支持向量机等。
识别准确率的高低取决于识别算法的设计和模型训练的效果。
最后,系统会将识别结果输出。
输出可以是字符的文本形式,也可以是字符的图片形式。
总结起来,车牌识别系统的原理是通过图像获取、车牌定位、字符分割、字符识别和结果输出等步骤,对车辆的车牌进行自动识别,实现自动化的车辆管理和监控。
车牌字符分割方法的研究的开题报告
车牌字符分割方法的研究的开题报告一、选题背景和意义随着城市化进程的不断加快,车辆数量急剧增加,交通状况也日益复杂,如何实现车辆识别以及智能调度已经成为一个重要议题。
而在车辆识别中,车牌字符分割是一个至关重要的环节,它对于正确、快速地识别车牌号码具有决定性的影响。
因此,对于车牌字符分割方法的研究具有重要的实际意义。
二、研究内容和目标本次研究旨在提出一种基于图像处理技术的车牌字符分割方法,通过对车牌图像进行预处理、二值化、特征提取等步骤,最终得到分割后的车牌字符,并能够在不同的场景中进行有效的应用。
具体而言,研究内容包括:1.车牌图像预处理,例如去除噪声、调整图像亮度等。
2.车牌图像二值化,将彩色车牌图像转化为黑白二值图像。
3.车牌字符分割,通过特征提取和分类算法,对车牌字符进行有效分割。
4.车牌字符分割方法的实现,编写计算机程序,对不同场景的车牌图像进行测试和验证。
三、研究方法本研究将采用以下方法:1.对现有的车牌字符分割方法进行调研和分析,了解其优缺点,并提出本方法的改进策略。
2.针对车牌字符分割的特征进行深入研究,包括颜色、形状、边缘等方面。
3.设计和实现车牌字符分割的算法流程,可以采用基于统计学算法或者深度学习算法。
4.评价本文提出的车牌字符分割方法的准确度、鲁棒性和效率。
四、研究的创新性和可行性本研究的创新性和可行性在于:1.针对车牌识别中的字符分割环节进行深入、系统的研究,提出了适应不同条件的车牌字符分割方法,对解决车牌识别难题具有重要意义。
2.本研究提出的车牌字符分割方法融合了图像处理、特征提取和分类算法等多种技术,具有较强的实用性和可行性。
3.本研究实现的车牌字符分割方法在实验中具有较好的分割效果,可以为车辆识别和智能交通系统的发展提供基础技术支持。
五、论文框架本文拟从以下几个方面进行论述:1.绪论,介绍车牌字符分割的背景和意义,调研国内外相关研究现状,并提出本次研究的目标和内容。
2.相关技术介绍,对车牌字符分割所涉及的图像处理、特征提取和分类算法等技术进行介绍和分析。
不定长车牌字符分割算法
捕 肆 精牌 定 ’符 骊. 诉 寻 主 誊 藉 氟 茬 运 位 靶 蒋 牌 中 萄 垂每 萼 毒 色 藏 位字 务 。藉 个 娄 霾 字 分 戈 霹 爱 詹 季 众 照 l 每 出
来的过穰: : 然后送l事符识剐l境识耕 一 蓟 系 一 本史提出 字符分喜算法在传统的垂直投影 的 I 海字符分喜的 l 基础上进行了改进 对
LI Yu n g n, O ofa E a ・ e M Gu - ng。 i ZHANG a - u n。 S n y a YE u z Xi -i
A b t a t Plt . ai s r c : ae I , t c o on,Ch rc e ta to aa t rExr c in。Ch r ce c g ii n a t h e i r c s e fv h ce Lie s ae Re - a a t rRe o n to 陀 he tr e ma n p o e s so e il c n e Plt c
1 字符个数为 5到 9个不等 : )
2 车 牌 中 间 的 无 效 大 间 隔 区域 为 1 2个 ; ) 到
1 引言
车 辆 牌 照 号 码 的 自动 识 别 成 为 车辆 管理 的必 要 和 有效 的
用 于 切分 南 非 车 牌 。
手段 , 车牌 自动识别系统适用 于公路收 费、 城市 交通管 理 、 封 闭区域车辆进 出管理 、 智能交通等应用系统等 。 当前 的车牌识别 系统 主要有 触发式 系统 和便 携 式系 统 ( 非触发式 ) 种。触发式系统使用传感 器 , 两 当车 辆通过 的时 候, 传感器触发拍摄装置 , 同时还可 以根据 自然光照条件进行 亮度补偿 。这样拍摄的车牌 图片一般车牌 区域大小 均匀 , 车 牌位置相对 比较 固定 , 噪声污染也小。比较而言 , 便携式系统 具有不需要触发装置 , 易安装 , 硬件成本低 的特点 , 同时 因 但 为拍摄角 度、 光照条件 、 天气 情况等客 观条件 的限制 , 所拍摄 得 图片质量相 对较 差 , 而且车 牌 区域 大小 不一 , 而且信 噪 比 低, 因此识别难度相对较大。 字符 分 割 是 在 车 牌 定 位 … 后 把 字 符 从 定 位 出 的 牌 照 区
常用的车牌字符分割方法
常用的车牌字符分割方法Common methods for segmenting license plate characters include:常用的车牌字符分割方法包括:1. Projection-based segmentation: This method involves scanning the image of the license plate horizontally or vertically to identify areas of interest based on pixel density. By analyzing the projection profiles, the boundaries of individual characters can be determined.1. 基于投影的分割方法:该方法涉及对车牌图像进行水平或垂直扫描,根据像素密度识别感兴趣的区域。
通过分析投影轮廓,可以确定单个字符的边界。
2. Connected component analysis: This approach identifies contiguous regions of pixels with similar properties (e.g., color or intensity) in the license plate image. Connected components corresponding to individual characters are then separated.2. 连通域分析:该方法在车牌图像中识别具有相似属性(例如颜色或强度)的连续像素区域。
然后,将对应于单个字符的连通域分离出来。
3. Machine learning-based segmentation: Modern approaches leverage machine learning algorithms, such as deep learning models, to segment characters from license plate images. These models are trained on annotated datasets to learn the characteristics of individual characters and can accurately identify and segment themin new images.3. 基于机器学习的分割方法:现代方法利用机器学习算法,如深度学习模型,对车牌图像中的字符进行分割。
基于连通域提取的车牌字符分割算法
cn etdaes nbn r i a e , cn ig h da e t i l o r t i l a dd t m n gt o n c v yo e o n c a i iay m g s sa n eajc n px s f a e px s n e r ii ec n e t i f e r n t e tg e e n h it t h
摘要: 车牌字符分割是车牌识别系统的三大关键技术之一。为了准确地进行字符分 割, 提高字符识别 的准确率 和识别 的速
度 , 出了一种改进的连通域提取车牌字符分割算法 , 提 算法通过扫描 目标像素 的若干 相邻像素后按照一定 的准则确定 目标
像素与相邻像素之 间的连通关系 , 可克服 同类算法中像 素重复标记和归并标记需大量运算 的缺陷 , 最后得到正确 的连 通标
a c ran t e rg tdsrbui n a d e ta tte c n c e rg o fs pa ain a a t Ex rme t ho ta ea g — s e i h it t h i i to n xr c h o ne td e i n o e rto tls. pe i n ss w h tt lo h
记 划 分 并 能 提 取 出各 个 分 离 的 连通 区域 。实 验 表 明 算 法能 够 准 确 快 速 地 识别 字 符 , 具 有 较 好 的 稳 健性 。 且
关 键 词 : 牌 字符 分 割 ; 值 图像 ; 素 标 记 ; 通 域 提取 车 二 像 连
中图分类号 :P9 . T 3 14
文献标识码 : A
Li e s a e Ch r c e g e t to s d o c n e Pl t a a t r Se m n a i n Ba e n Co ne t d Co po n t a to n ce m ne t Ex r c i n
车牌识别的步骤
车牌识别的步骤一般包括以下几个环节:
图像获取:使用摄像机或其他图像采集设备获取车辆的图像。
通常会选择安装在适当位置的高分辨率摄像机来拍摄车辆的前、后或侧面图像。
图像预处理:对获取的图像进行预处理,以提高后续识别的准确性。
预处理包括图像去噪、图像增强、图像分割等处理步骤。
车牌定位:在预处理后的图像中,使用车牌定位算法来准确定位车牌的位置。
车牌定位算法通常基于车牌的特征,如形状、颜色等进行判断和筛选。
字符分割:将定位到的车牌图像进行字符分割,将每个字符分离开来。
字符分割是车牌识别的关键步骤之一,需要考虑车牌上字符的大小、间距以及字符之间的相互影响。
字符识别:对分割后的字符进行识别,将字符转化为相应的文字或数字。
字符识别可以使用模式识别算法、神经网络等方法进行,常用的方法包括基于特征的识别、模板匹配、深度学习等。
汽车车牌自动定位与字符分割
I=imread('Car.jpg'); %读入图片figure(1),imshow(I); %显示出图片[y,x,z]=size(I);myI=double(I); %转化数据为双精度型%%%%%%%%%%% RGB to HIS %%%%%%%%tic % 测定算法执行的时间,开始计时%%%%%%%%%%% 统计分析%%%%%%%%%%%%%%%%=========== Y 方向=============Blue_y=zeros(y,1);for i=1:yfor j=1:xif((myI(i,j,1)<=30)&&((myI(i,j,2)<=62)&&(myI(i,j,2)>=51))&&((myI(i,j,3)<=142)&&(myI(i,j,3) >=119)))% 蓝色RGB的灰度范围Blue_y(i,1)= Blue_y(i,1)+1; % 蓝色象素点统计endendend[temp MaxY]=max(Blue_y); % Y方向车牌区域确定PY1=MaxY;while ((Blue_y(PY1,1)>=5)&&(PY1>1))PY1=PY1-1;endPY2=MaxY;while ((Blue_y(PY2,1)>=5)&&(PY2<y))PY2=PY2+1;endIY=I(PY1:PY2,:,:);%======================% X 方向%======================Blue_x=zeros(1,x); % 进一步确定X方向的车牌区域for j=1:xfor i=PY1:PY2if((myI(i,j,1)<=30)&&((myI(i,j,2)<=62)&&(myI(i,j,2)>=51))&&((myI(i,j,3)<=142)&&(myI(i,j,3) >=119)))Blue_x(1,j)= Blue_x(1,j)+1;endendendPX1=1;while ((Blue_x(1,PX1)<3)&&(PX1<x))PX1=PX1+1;endPX2=x;while ((Blue_x(1,PX2)<8)&&(PX2>PX1))PX2=PX2-1;end%======对车牌区域的修正=========PX1=PX1-2; %PX2=PX2+2;Plate=I(PY1:PY2,PX1-2:PX2+2,:);%======像素点数在X、Y方向上的统计并且显示数量统计图t=toc; % 读取计时figure(2),plot(Blue_x);gridfigure(3),plot(Blue_y);gridfigure(4),imshow(IY);figure(5),imshow(Plate);%======字符分割并且分别显示IA=I(PY1:PY2,PX1-2:PX1+12,:);figure(6),imshow(IA);IB=I(PY1:PY2,PX1+ 12:PX1+26,:);figure(7),imshow(IB);IC=I(PY1:PY2,PX1+28:PX1+44,:);figure(8),imshow(IC);ID=I(PY1:PY2,PX1+44:PX1+56,:);figure(9),imshow(ID);IE=I(PY1:PY2,PX1+58:PX1+70,:);figure(10),imshow(IE);IF=I(PY1:PY2,PX1+70:PX1+84,:);figure(11),imshow(IF);IG=I(PY1:PY2,PX1+84:PX2+2,:);figure(12),imshow(IG);%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 字符分割模块算法% 定位剪切后的彩色车牌图像--灰度--二值化--统一到黑底白字--去除上下边框% --切割出最小范围--滤波--形态学处理--分割出7个字符% 去除上下边框算法:% 1.黑白跳变小于阈值则被视为背景;2.连续白线大于某阈值则该白线被认为是背景% 3.单行白色大于阈值则被认为是背景,考虑FLAG的值;% 4.做完以上处理后,上边1/2 中搜索连续两条黑线,认为该黑线以上为背景;在下边1/2 中搜索连续两条黑线,认为该黑线以下为背景% 归一化为40*20 ,商用系统程序中归一化为32*16 ,此处仅演示作用function [d]=lpcseg(jpg)I=imread('car1.jpg');I1=rgb2gray(I);I2=edge(I1,'robert',0.15,'both');se=[1;1;1];I3=imerode(I2,se);se=strel('rectangle',[25,25]);I4=imclose(I3,se);I5=bwareaopen(I4,2000);[y,x,z]=size(I5);myI=double(I5);ticwhite_y=zeros(y,1);for i=1:yfor j=1:xif(myI(i,j,1)==1)white_y(i,1)= white_y(i,1)+1;endendend[temp MaxY]=max(white_y);PY1=MaxY;while ((white_y(PY1,1)>=5)&&(PY1>1))PY1=PY1-1;endPY2=MaxY;while ((white_y(PY2,1)>=5)&&(PY2<y))PY2=PY2+1;endIY=I(PY1:PY2,:,:);white_x=zeros(1,x);for j=1:xfor i=PY1:PY2if(myI(i,j,1)==1)white_x(1,j)= white_x(1,j)+1;endendendPX1=1;while ((white_x(1,PX1)<3)&&(PX1<x))PX1=PX1+1;endPX2=x;while ((white_x(1,PX2)<3)&&(PX2>PX1))PX2=PX2-1;endPX1=PX1-1;PX2=PX2+1;dw=I(PY1:PY2-8,PX1:PX2,:);t=toc;figure(1),subplot(3,2,1),imshow(dw),title('定位剪切后的彩色车牌图像')imwrite(dw,'dw.jpg');[filename,filepath]=uigetfile('dw.jpg','输入一个定位裁剪后的车牌图像');jpg=strcat(filepath,filename);a=imread(jpg);%figure(1);subplot(3,2,1),imshow(a),title('1.定位剪切后的彩色车牌图像')b=rgb2gray(a);imwrite(b,'2.车牌灰度图像.jpg');figure(1);subplot(3,2,2),imshow(b),title('2.车牌灰度图像')g_max=double(max(max(b)));g_min=double(min(min(b)));T=round(g_max-(g_max-g_min)/3); % T 为二值化的阈值[m,n]=size(b);d=(double(b)>=T); % d:二值图像imwrite(d,'3.车牌二值图像.jpg');figure(1);subplot(3,2,3),imshow(d),title('3.车牌二值图像')% 旋转rotate=0;d=imread('3.车牌二值图像.jpg');bw=edge(d);[m,n]=size(d);theta=1:179;% bw 表示需要变换的图像,theta 表示变换的角度% 返回值r 表示的列中包含了对应于theta中每一个角度的Radon 变换结果% 向量xp 包含相应的沿x轴的坐标[r,xp]=radon(bw,theta);i=find(r>0);[foo,ind]=sort(-r(i));k=i(ind(1:size(i)));[y,x]=ind2sub(size(r),k);[mm,nn]=size(x);if mm~=0 && nn~=0j=1;while mm~=1 && j<180 && nn~=0i=find(r>j);[foo,ind]=sort(-r(i));k=i(ind(1:size(i)));[y,x]=ind2sub(size(r),k);[mm,nn]=size(x);j=j+1;endif nn~=0if x % Enpty matrix: 0-by-1 when x is an enpty array.x=x;else % 可能x 为空值x=90; % 其实就是不旋转endd=imrotate(d,abs(90-x)); % 旋转图像rotate=1;endendimwrite(d,'4.Radon 变换旋转后的二值图像.jpg');figure(1),subplot(3,2,4),imshow(d),title('4.Radon 变换旋转后的二值图像')% 统一到白底黑字[m,n]=size(d);% flag=0 表示原来就是白底黑字,否则表示原来是黑底白字flag=0;c=d([round(m/3):m-round(m/3)],[round(n/3):n-round(n/3)]);if sum(sum(c))/m/n*9>0.5d=~d;flag=1;end% 对反色后的图像预处理,整列几乎为白的认为是背景if flag==1for j=1:nif sum(sum(d(:,j)))/m>=0.95d(:,j)=0;endend% 对以上处理后的图像再处理% 在左边1/2 处找连续两条黑线,认为该黑线左边为背景;在右边1/2 处找连续两条黑线,认为该黑线右边是背景% 左边1/2jj=0;for j=1:round(n/2)if sum(sum(d(:,[j:j+0])))==0jj=j;endendd(:,[1:jj])=0;% 右边1/2for j=n:-1:round(n/2)if sum(sum(d(:,[j-0:j])))==0jj=j;endendd(:,[jj:n])=0;endimwrite(d,'5.统一成黑底白字.jpg');figure(1),subplot(3,2,5),imshow(d),title('5.背景色统一成黑底白字') figure(2),subplot(5,1,1),imshow(d),title('5.黑底白字的二值车牌图像')% 去除上下边框% STEP 1 黑白跳变小于阈值则被视为背景% 上面2/5y1=10; % y1: 跳变阈值for i=1:round(m/5*2)count=0;jump=0;temp=0;for j=1:nif d(i,j)==1temp=1;elsetemp=0;endif temp==jumpcount=count;elsecount=count+1;endjump=temp;endif count<y1d(i,:)=0;endend% 下面2/5for i=3*round(m/5):mcount=0;jump=0;temp=0;for j=1:nif d(i,j)==1elsetemp=0;endif temp==jumpcount=count;elsecount=count+1;endjump=temp;endif count<y1d(i,:)=0;endendimwrite(d,'6.黑白跳变小于某阈值的行则被视为背景.jpg');figure(2),subplot(5,1,2),imshow(d),title('6.黑白跳变小于某阈值的行则被视为背景')% STEP 2 单行白色大于阈值则被认为是背景,考虑FLAG 的值% 上面2/5y2=round(n/2); % y2: 阈值for i=1:round(m/5*2)if flag==0temp=sum(d(i,:));y2=round(n/2);if temp>y2d(i,:)=0;endelsetemp=m-sum(d(i,:));y2=m-round(n/2);if temp<y2d(i,:)=0;endendend% 下面2/5for i=round(3*m/5):mif flag==0temp=sum(d(i,:));y2=round(n/2);if temp>y2d(i,:)=0;endelsetemp=m-sum(d(i,:));y2=m-round(n/2);if temp<y2endendendimwrite(d,'7.单行白色点总数大于某阈值则该行被认为是背景.jpg');figure(2),subplot(5,1,3),imshow(d),title('7.单行白色点总数大于某阈值则该行被认为是背景') % STEP 3 单行白色大于阈值则被认为是背景,考虑FLAG 的值% 上面2/5y2=round(n/2); % y2: 阈值for i=1:round(m/5*2)if flag==0temp=sum(d(i,:));y2=round(n/2);if temp>y2d(i,:)=0;endelsetemp=m-sum(d(i,:));y2=m-round(n/2);if temp<y2d(i,:)=0;endendend% 下面2/5for i=round(3*m/5):mif flag==0temp=sum(d(i,:));y2=round(n/2);if temp>y2d(i,:)=0;endelsetemp=m-sum(d(i,:));y2=m-round(n/2);if temp<y2d(i,:)=0;endendendimwrite(d,'8.单行白色点总数大于某阈值则该行被认为是背景.jpg');figure(2),subplot(5,1,4),imshow(d),title('8.单行白色点总数大于某阈值则该行被认为是背景') % STEP 4 做完以上处理后,上边1/2 中搜索连续两条黑线,认为该黑线以上为背景;% 在下边1/2 中搜索连续两条黑线,认为该黑线以下为背景% 上边1/2for i=1:round(m/2)if sum(sum(d([i,i+0],:)))==0ii=i;endendd([1:ii],:)=0;% 下边1/2for i=m:-1:round(m/2)if sum(sum(d([i-0:i],:)))==0ii=i;endendd([ii:m],:)=0;imwrite(d,'9.搜索上下两条黑线后的结果.jpg');figure(2),subplot(5,1,5),imshow(d),title('9.搜索上下两条黑线后的结果')% 反旋转if rotate==1d=imrotate(d,-abs(x-90));endimwrite(d,'10.反旋转去毛刺后.jpg');figure(3),subplot(3,2,1),imshow(d),title('10.反旋转去毛刺后')% 切割处最小范围d=qiege(d);e=d;imwrite(d,'11.切割处最小范围.jpg');figure(3),subplot(3,2,2),imshow(d),title('11.切割处最小范围')figure(3),subplot(3,2,3),imshow(d),title('11.均值滤波前')% 滤波h=fspecial('average',3);d=im2bw(round(filter2(h,d)));imwrite(d,'12.均值滤波后.jpg');figure(3),subplot(3,2,4),imshow(d),title('12.均值滤波后')% 某些图像进行操作% 膨胀或腐蚀% se=strel('square',3); % 使用一个3X3的正方形结果元素对象对创建的图像进行膨胀% 'line'/'diamond'/'ball'...se=eye(2); % eye(n) returns the n-by-n identity matrix 单位矩阵[m,n]=size(d);if bwarea(d)/m/n>=0.365d=imerode(d,se);elseif bwarea(d)/m/n<=0.235d=imdilate(d,se);endimwrite(d,'13.膨胀或腐蚀处理后.jpg');figure(3),subplot(3,2,5),imshow(d),title('13.膨胀或腐蚀处理后')% 寻找连续有文字的块,若长度大于某阈值,则认为该块有两个字符组成,需要分割d=qiege(d);[m,n]=size(d);figure,subplot(2,1,1),imshow(d),title(n)k1=1;k2=1;s=sum(d);j=1;while j~=nwhile s(j)==0j=j+1;endk1=j;while s(j)~=0 && j<=n-1j=j+1;endk2=j-1;if k2-k1>=round(n/6.5)[val,num]=min(sum(d(:,[k1+5:k2-5])));d(:,k1+num+5)=0; % 分割endend% 再切割d=qiege(d);% 切割出7 个字符y1=10;y2=0.25;flag=0;word1=[];while flag==0[m,n]=size(d);left=1;wide=0;while sum(d(:,wide+1))~=0wide=wide+1;endif wide<y1 % 认为是左侧干扰d(:,[1:wide])=0;d=qiege(d);elsetemp=qiege(imcrop(d,[1 1 wide m]));[m,n]=size(temp);all=sum(sum(temp));two_thirds=sum(sum(temp([round(m/3):2*round(m/3)],:)));if two_thirds/all>y2flag=1;word1=temp; % WORD 1endd(:,[1:wide])=0;d=qiege(d);endend% 分割出第二个字符[word2,d]=getword(d);% 分割出第三个字符[word3,d]=getword(d);% 分割出第四个字符[word4,d]=getword(d);% 分割出第五个字符[word5,d]=getword(d);% 分割出第六个字符[word6,d]=getword(d);% 分割出第七个字符[word7,d]=getword(d);subplot(5,7,1),imshow(word1),title('1');subplot(5,7,2),imshow(word2),title('2');subplot(5,7,3),imshow(word3),title('3');subplot(5,7,4),imshow(word4),title('4');subplot(5,7,5),imshow(word5),title('5');subplot(5,7,6),imshow(word6),title('6');subplot(5,7,7),imshow(word7),title('7');[m,n]=size(word1);% 商用系统程序中归一化大小为32*16,此处演示word1=imresize(word1,[40 20]);word2=wordprocess(word2);word3=wordprocess(word3);word4=wordprocess(word4);word5=wordprocess(word5);word6=wordprocess(word6);word7=wordprocess(word7);subplot(5,7,15),imshow(word1),title('1');subplot(5,7,16),imshow(word2),title('2');subplot(5,7,17),imshow(word3),title('3');subplot(5,7,18),imshow(word4),title('4');subplot(5,7,19),imshow(word5),title('5');subplot(5,7,20),imshow(word6),title('6');subplot(5,7,21),imshow(word7),title('7');imwrite(word1,'14.字符分割归一化后1.jpg'); imwrite(word2,'14.字符分割归一化后2.jpg'); imwrite(word3,'14.字符分割归一化后3.jpg'); imwrite(word4,'14.字符分割归一化后4.jpg'); imwrite(word5,'14.字符分割归一化后5.jpg'); imwrite(word6,'14.字符分割归一化后6.jpg'); imwrite(word7,'14.字符分割归一化后7.jpg');%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%clcword='';word(1)=wordrec(word1);word(2)=wordrec(word2);word(3)=wordrec(word3);word(4)=wordrec(word4);word(5)=wordrec(word5);word(6)=wordrec(word6);word(7)=wordrec(word7);clcsave I 'word1' 'word2' 'word3' 'word4' 'word5' 'word6' 'word7'clearload I;load bp net;word='';word(1)=wordrec(word1);word(2)=wordrec(word2);word(3)=wordrec(word3);word(4)=wordrec(word4);word(5)=wordrec(word5);word(6)=wordrec(word6);word(7)=wordrec(word7);word=strcat('识别结果:',word);subplot(5,3,14),imshow([]),title(word,'fontsize',24)% 该子程序用于切割出最小范围function e=qiege(d)[m,n]=size(d);top=1;bottom=m;left=1;right=n; % initwhile sum(d(top,:))==0 && top<=mtop=top+1;endwhile sum(d(bottom,:))==0 && bottom>=1bottom=bottom-1;endwhile sum(d(:,left))==0 && left<=nleft=left+1;endwhile sum(d(:,right))==0 && right>=1right=right-1;enddd=right-left;hh=bottom-top;e=imcrop(d,[left top dd hh]);% 分割字符function [word,result]=getword(d)word=[];flag=0;y1=8;y2=0.5;% if d==[]% word=[];% elsewhile flag==0[m,n]=size(d);wide=0;while sum(d(:,wide+1))~=0 && wide<=n-2wide=wide+1;endtemp=qiege(imcrop(d,[1 1 wide m]));[m1,n1]=size(temp);if wide<y1 && n1/m1>y2d(:,[1:wide])=0;if sum(sum(d))~=0d=qiege(d); % 切割出最小范围else word=[];flag=1;endelseword=qiege(imcrop(d,[1 1 wide m]));d(:,[1:wide])=0;if sum(sum(d))~=0;d=qiege(d);flag=1;else d=[];endendend%endresult=d;%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 该子程序用于字符归一化处理function d=wordprocess(d)[m,n]=size(d);%top 1/3, bottom 1/3for i=1:round(m/3)if sum(sum(d([i:i+0],:)))==0ii=i;d([1:ii],:)=0;endendfor i=m:-1:2*round(m/3)if sum(sum(d([i-0:i],:)))==0ii=i;d([ii:m],:)=0;endendif n~=1d=qiege(d);end% d=..这个可以通过训练过程设置大小% d=imresize(d,[32 16]); % 商用系统程序中归一划大小为:32*16d=imresize(d,[40 20]);%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 编号:A-Z 分别为1-26; 0-9 分别为27-36;% 京津沪渝港澳吉辽鲁豫冀鄂湘晋青皖苏% 赣浙闽粤琼台陕甘云川贵黑藏蒙桂新宁% 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59% 60 61 62 63 64 65 66 67 68 69 70% 使用BP 网络function word=wordrec(xx)% clear% clcload bp net;xx=im2bw(xx);xx=double(xx(:)); % 使用阈值将图像转换为二进制图像a=sim(net,xx); % 归一划为:32*16,则xx=512*1;[val,num]=max(a);if num<=26word=char(double('A')+num-1);elseif num<=36word=char(double('0')+num-1-26);elseswitch numcase 37word='京';case 38word='津';case 39word='沪';word='渝'; case 41word='港'; case 42word='澳'; case 43word='吉'; case 44word='辽'; case 45word='鲁'; case 46word='豫'; case 47word='冀'; case 48word='鄂'; case 49word='湘'; case 50word='晋'; case 51word='青'; case 52word='皖'; case 53word='苏'; case 54word='赣'; case 55word='浙'; case 56word='闽'; case 57word='粤'; case 58word='琼'; case 59word='台'; case 60word='陕'; case 61word='甘';word='云';case 63word='川';case 64word='贵';case 65word='黑';case 66word='藏';case 67word='蒙';case 68word='桂';case 69word='新';case 70word='宁';endend。
基于投影的车牌字符分割方法_黄文杰
现代计算机(总第三一三期0引言本文利用车牌精确定位的结果,运用像素水平投影与竖直投影的方法,结合车牌字符的先验信息,在不需要设计特征函数与判决函数的条件下,就可以准确地对车牌字符进行切割。
同时,针对某些汉字如川、浙、湘、沪、津及皖、桂等易被错误分割或漏割的情况,对汉字左右边界的起始位置进行标记,利用此标记获得该汉字的原始灰度图像,对其单独进行分割及二值化,避免汉字笔画退化为噪声。
1车牌的水平投影从图1可以看出,在车牌区域中存在边框及铆钉的存在,影响车牌字符的分割,因此,在字符分割前需要消除边框及铆钉等噪声对车牌字符分割的影响。
如图2所示,由于已经对车牌区域进行了位置矫正,使得车牌区域基本保持矩形形状,因此,可以利用车牌区域像素水平投影的方法消除车牌边框及铆钉。
具体算法如下:图1车牌区域(1)对车牌区域作竖直像素差分,以消除背景的影响,如图3所示。
此步骤是消除车牌区域边框及铆钉等噪声的关键。
图2像素水平投影图3像素竖直差分(2)对车牌区域中的各点作像素水平投影pixel -Sum[i],I 为车牌区域的宽度。
(3)从开始搜索,当pixelSum[i]12时,标志flag=0,当遇到pixelSum [i]>12,记录该i 值作为结束位置end ,如果此时flag=0,那么并且记录首个使得pixel -Sum[i]>12的i 值作为开始位置start ,同时设置标志flag=1,当时,记录此时的开始位置start 与结束位置end ,作为字符的竖直区域,否则继续搜索。
图4去除车牌的边框及铆钉结果去除车牌的边框及铆钉结果如图4所示,说明经过该算法处理后,能够有效地消除车牌边框及铆钉等,,,,,,基于投影的车牌字符分割方法黄文杰(淮阴工学院交通工程系,淮安223003)摘要:关键词:车牌识别;字符分割;投影收稿日期:2009-06-22修稿日期:2009-07-26作者简介:黄文杰(1977-),男,研究方向为智能交通、模式识别、图像重构运用像素水平投影与竖直投影的方法,结合车牌字符的先验信息可以准确地对车牌字符进行切割。
matlab对彩色车牌字符切割代码
一、引言在计算机视觉和图像处理领域,对彩色车牌的字符进行切割是一个重要的问题。
在实际应用中,比如车牌识别系统中,准确地将车牌上的字符进行切割可以为后续的字符识别提供可靠的输入。
而MATLAB作为一种强大的科学计算软件,其丰富的图像处理工具和灵活的编程环境使得它成为了许多研究者和工程师处理图像问题的首选工具。
本文将介绍MATLAB对彩色车牌字符切割的代码实现方法。
二、彩色车牌图像预处理1. 车牌图像的读取在MATLAB中,可以使用imread函数读取彩色车牌图像,将其存储为一个三维的数组,分别表示红、绿、蓝三个通道的像素值。
2. 图像的灰度化对于彩色车牌图像,我们首先需要将其转换为灰度图像,可以使用rgb2gray函数来实现。
3. 图像的二值化我们可以对灰度图像进行二值化处理,将车牌字符部分变为白色,背景部分变为黑色。
可以使用im2bw函数并调节合适的阈值来实现。
三、车牌字符的定位1. 边缘检测在得到车牌图像的二值图像之后,可以利用MATLAB提供的边缘检测函数,比如edge函数对图像进行边缘检测,以便后续的字符定位。
2. 车牌区域的定位利用边缘检测的结果,我们可以利用MATLAB提供的连通区域分析函数,比如bwconp函数来对车牌区域进行定位,并将其提取出来。
3. 车牌字符的切割在得到车牌区域之后,可以利用MATLAB提供的图像处理函数,比如imcrop函数来对车牌区域进行字符切割,得到单独的字符图像。
四、代码实现以下是MATLAB对彩色车牌字符切割的代码实现:```读取彩色车牌图像I = imread('car_plate.jpg');将图像转换为灰度图像I_gray = rgb2gray(I);对灰度图像进行二值化处理I_bw = im2bw(I_gray, 0.5);对二值图像进行边缘检测I_edge = edge(I_bw, 'sobel');进行连通区域分析cc = bwconp(I_edge);对车牌区域进行切割plate_region = regionprops(cc, 'BoundingBox');for i = 1:cc.NumObjects切割字符区域character_image = imcrop(I_gray,plate_region(i).BoundingBox);保存字符图像imwrite(character_image, ['character' num2str(i) '.jpg']);end```五、实验结果经过以上步骤,我们可以得到彩色车牌字符切割的结果,得到单独的字符图像,为后续的字符识别提供了可靠的输入。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
图像处理包括图像二值化、车牌定位、字符分隔、字符识别。
每一步都关系系统成功与否以及好坏。
如果图片二值化不好就不方便车牌定位,如果定位的车牌图片不准确就谈不上字符的切割,字符图片切割不好就难以识别。
这些应该很好理解,可见成员之间需要很好的默契。
而我负责了图像处理中的字符分隔模块,起初我不知道位图形式以及如何读取位图,可见我获取信息的主动性和能力并不好。
非常感谢其他组员提供了读取位图像素数据的相关方法,才能使我能放心去思考切割的算法,而不必去担心如何获取数据的问题。
我使用了一种字符像素横向和纵向扫描的算法,得到字符在横向和纵向的像素分布波形,通常是缓慢的连续变化,车牌越模糊,变化越缓慢。
自然,波峰是字符区,波谷是字符间的空隙区。
它们的分界点并不明显,必然需要找到介于波峰与波谷之间的一个阀值,将波形变成01直方波形。
那么阀值自然是个关键,如果定得不准,就可能切不出所有字符,这是我之前遇到的问题,那时我固定了阀值,使它介于平均波峰值和平均波谷值之间的某个固定点,但这通常只能切割出模糊图片的部分字符,因为有些波峰和波谷并没有被切分开来。
于是我采用了另一种策略,即使用动态扫描,从最小的波谷扫到最大的波峰,并不断计算切得的波峰数量(实际就是字符数量)。
然后判断这个切割数是否符合实际车牌上的字符数量,如果符合,可以停止扫描,切割位置可以明确定在波峰和波谷的变化点上。
当然,我进行了各种优化,比如更多判断来排除各种车牌边框等干扰。
在DOS窗口上经过反复的数据显示测试,终于得到了非常不错的字————————————————————————————————————————————(1)利用字符像素XY方向扫描;(2)分析波形;(3)动态指定阀值;(4)获得01分布;(5)判断波形变化次数;(6)去干扰;(7)获得切割位置;时间有限,有不完善之处可以去本人博客提问:/flashforyou#pragma once#include <cstring>#include <cmath> //数学函数库#include <cstdio>#include <cstdlib>#include <cmalloc>#include "stdafx.h"#include <complex>#define WIDTHBYTES(bits) (((bits)+31)/32*4)/////////////////////////////////////typedef unsigned char BYTE;typedef unsigned short WORD;typedef unsigned long DWORD;typedef long LONG;///////////////////////////////////////***位图文件头信息结构定义//其中不包含文件类型信息(由于结构体的内存结构决定,要是加了的话将不能正确读取文件信息)typedef struct tagBITMAPFILEHEADER {DWORD bfSize; //文件大小WORD bfReserved1; //保留字,不考虑WORD bfReserved2; //保留字,同上DWORD bfOffBits; //实际位图数据的偏移字节数,即前三个部分长度之和} BITMAPFILEHEADER;///////////////////////////////////////***信息头BITMAPINFOHEADER结构,其定义如下:typedef struct tagBITMAPINFOHEADER{//public:DWORD biSize; //指定此结构体的长度,为40LONG biWidth; //位图宽LONG biHeight; //位图高WORD biPlanes; //平面数,为1WORD biBitCount; //采用颜色位数,可以是1,2,4,8,16,24,新的可以是32 DWORD biCompression; //压缩方式,可以是0,1,2,其中0表示不压缩DWORD biSizeImage; //实际位图数据占用的字节数LONG biXPelsPerMeter; //X方向分辨率LONG biYPelsPerMeter; //Y方向分辨率DWORD biClrUsed; //使用的颜色数,如果为0,则表示默认值(2^颜色位数)DWORD biClrImportant; //重要颜色数,如果为0,则表示所有颜色都是重要的} BITMAPINFOHEADER;/////////////////////////////////////////***调色板Palette,当然,这里是对那些需要调色板的位图文件而言的。
24位和32位是不需要调色板的。
//(似乎是调色板结构体个数等于使用的颜色数。
)typedef struct tagRGBQUAD {//public:BYTE rgbBlue; //该颜色的蓝色分量BYTE rgbGreen; //该颜色的绿色分量BYTE rgbRed; //该颜色的红色分量BYTE rgbReserved; //保留值} RGBQUAD;//////////////////////////////////////typedef struct tagHSI {//public:double hsiH; //该颜色的Hdouble hsiS; //该颜色的Sdouble hsiI; //该颜色的Idouble hsiTh; //该颜色的Th} HSIInfo;//////////////////////////////////////typedef struct tagCUT {//public:int no; //切块编号int up; //切块的上坐标int down; //切块的下坐标int left; //切块的左坐标int right; //切块的右坐标} CUT;//////////////////////////////////////////////////***RGB输出函数//参数说明:<--调色板对象-->void showRgbQuan(tagRGBQUAD* pRGB){//printf("(%-3d,%-3d,%-3d) ",pRGB->rgbRed,pRGB->rgbGreen,pRGB->rgbBlue);if(pRGB->rgbRed>0)printf(" ");elseprintf("[X]");}//////////////////////////////////////////////////***设定位图文件头信息//参数说明:<>void MakeBmpHead(BITMAPFILEHEADER &pBmpHead,DWORD biSizeImage){pBmpHead.bfSize=biSizeImage+62;pBmpHead.bfReserved1=0;pBmpHead.bfReserved2=0;pBmpHead.bfOffBits=62;}/////////////////////////////////////////////////***设定位图信息头信息//参数说明:<位图信息头,为图宽,为图高>void MakeBmpInforHead(tagBITMAPINFOHEADER &pBmpInforHead,LONG width,LONG height){ pBmpInforHead.biSize=40;pBmpInforHead.biWidth=width;pBmpInforHead.biHeight=height;pBmpInforHead.biPlanes=1;pBmpInforHead.biBitCount=1;pBmpInforHead.biCompression=0;pBmpInforHead.biSizeImage=WIDTHBYTES(width) * height;pBmpInforHead.biXPelsPerMeter=3780;pBmpInforHead.biYPelsPerMeter=3780;pBmpInforHead.biClrUsed=0;pBmpInforHead.biClrImportant=0;}////////////////////////////////////////////////***设定调色板信息//参数说明:<调色板对象>void MakeColorPlant(tagRGBQUAD *pRgb,long nPlantNum) {for(int i=0;i<nPlantNum;i++){pRgb[i].rgbRed=i*(255);pRgb[i].rgbGreen=i*(255);pRgb[i].rgbBlue=i*(255);pRgb[i].rgbReserved=i;}}/////////////////////////////////////////////////***创建BMP文件//参数说明:<bmp文件名,调色板对象,宽度,高度>void MakeBmpHeader(char* strFile,tagRGBQUAD* dataOfBmp,LONG widthBmp,CUT cut){ FILE* pf;BITMAPFILEHEADER bitHead;BITMAPINFOHEADER bitInfoHead;//////////////int up=cut.up;int down=cut.down;int left=cut.left;int right=cut.right;LONG widthCut=LONG(right-left+1);LONG heightCut=LONG(up-down+1);int no=cut.no;char* charNo;if(no<10){charNo=new char[3];charNo[0]='_';charNo[1]=(char)(48+no);charNo[2]='\0';}else if(no<100){charNo=new char[4];charNo[0]='_';charNo[1]=(char)(48+no-no%10);charNo[2]=(char)(48+no%10);charNo[3]='\0';}else{printf("数字大,不考虑!");return;}//构造生成图片的文件名char* strnFile= new char[100];for(int i = 0; strFile[i] != '\0'; i++){if(i==99){printf("Name of File too long!");return;}strnFile[i]=strFile[i];if(strFile[i] == '.'){strnFile[i] = '\0';break;}}strcat(charNo,".bmp");strcat(strnFile,charNo);pf = fopen(strnFile,"wb");//打开文件//文件头信息设定WORD fileType=0x4D42;fwrite(&fileType,1,sizeof(WORD),pf); //===========================RMakeBmpInforHead(bitInfoHead,widthCut,heightCut);MakeBmpHead(bitHead,bitInfoHead.biSizeImage);fwrite(&bitHead,1,sizeof(tagBITMAPFILEHEADER),pf); //====================Rfwrite(&bitInfoHead,1,sizeof(BITMAPINFOHEADER),pf);//=======================R//调色板信息设定long nPlantNum = long(pow(2,double(bitInfoHead.biBitCount))); // Mix color Plant Number;tagRGBQUAD *pRgb = (tagRGBQUAD *)malloc(nPlantNum*sizeof(tagRGBQUAD));memset(pRgb,0,nPlantNum*sizeof(tagRGBQUAD)); //都设置为0MakeColorPlant(pRgb,nPlantNum);fwrite(pRgb,4,nPlantNum,pf); //===================R//写入像素信息BYTE *pColorData = (BYTE *)malloc(bitInfoHead.biSizeImage);memset(pColorData,0,bitInfoHead.biSizeImage*sizeof(BYTE));int l_width = WIDTHBYTES(widthCut); //4字节整倍化for(int i = down; i < up+1; i++ )for(int j = left; j < right+1; j++ ){int k = (i-down)*l_width + (j-left)/8; //k:取得该像素颜色数据在实际数据数组中的序号int index = i*widthBmp+j; //index:取得该像素在实际像素信息数组中的序号BYTE dataAns = (dataOfBmp[index].rgbBlue+dataOfBmp[index].rgbGreen+dataOfBmp[index].rgbRed)/3/128;//25 5/128或0/128switch((j-left)%8){case 0:pColorData[k] |= (dataAns<<7);break;case 1:pColorData[k] |= (dataAns<<6);break;case 2:pColorData[k] |= (dataAns<<5);break;case 3:pColorData[k] |= (dataAns<<4);break;case 4:pColorData[k] |= (dataAns<<3);break;case 5:pColorData[k] |= (dataAns<<2);break;case 6:pColorData[k] |= (dataAns<<1);break;case 7:pColorData[k] |= dataAns;break;}}fwrite(pColorData,1,bitInfoHead.biSizeImage,pf);//====================R printf("Build sucessful!\n");if(fclose(pf)==0){printf("closed!!!\n");}free(pColorData);free(pRgb);return ;}/////////////////////////////////////////////////////***处理BMP文件//参数说明:<车牌bmp文件名,切割字符数>void DealFile(char* strFile,int numOfCut){//puts(strFile);if(numOfCut<1)return;//防止输入负数或者0,因为无意义;BITMAPFILEHEADER bitHead;BITMAPINFOHEADER bitInfoHead;FILE* pfile;pfile = fopen(strFile,"rb"); //打开文件if(pfile!=NULL){printf("file bkwood.bmp open success.\n");//读取位图文件头信息//////////////////WORD fileType;fread(&fileType,1,sizeof(WORD),pfile);if(fileType != 0x4D42){printf("file is not .bmp file!");return ;}fread(&bitHead,1,sizeof(tagBITMAPFILEHEADER),pfile);////////////////////////////////////////读取位图信息头信息///////////////////fread(&bitInfoHead,1,sizeof(tagBITMAPINFOHEADER),pfile);//////////////////////////////////////}else{printf("file open fail!\n");return ;}tagRGBQUAD *pRgb ;if(bitInfoHead.biBitCount != 8){printf("非256色BMP位图!\n"); //输出像素信息return;}//读取调色盘结信息long nPlantNum = long(pow(2,double(bitInfoHead.biBitCount))); // Mix color Plant Number;pRgb=(tagRGBQUAD *)malloc(nPlantNum*sizeof(tagRGBQUAD));memset(pRgb,0,nPlantNum*sizeof(tagRGBQUAD));fread(pRgb,4,nPlantNum,pfile);printf("Color Plate Number: %d\n",nPlantNum);printf("\n");int width = bitInfoHead.biWidth;int height = bitInfoHead.biHeight;//分配内存空间把源图存入内存int l_width = WIDTHBYTES(width* bitInfoHead.biBitCount); //计算位图的实际宽度并确保它为4的倍数BYTE *pColorData=(BYTE *)malloc(height*l_width);memset(pColorData,0,height*l_width);long nData = height*l_width;//把位图数据信息读到数组里fread(pColorData,1,nData,pfile);//将位图数据转化为RGB数据tagRGBQUAD* dataOfBmp;dataOfBmp = (tagRGBQUAD *)malloc(width*height*sizeof(tagRGBQUAD));//用于保存各像素对应的RGB数据memset(dataOfBmp,0,width*height*sizeof(tagRGBQUAD)); //将内存空间dataOfBmp的前0个字节值设置为width*height*sizeof(tagRGBARAD);////处理8位图////////////////////////////int k,index=0;for(int i=0;i<height;i++)for(int j=0;j<width;j++){BYTE mixIndex= 0;k = i*l_width + j;mixIndex = pColorData[k];dataOfBmp[index].rgbRed = pRgb[mixIndex].rgbRed;dataOfBmp[index].rgbGreen = pRgb[mixIndex].rgbGreen;dataOfBmp[index].rgbBlue = pRgb[mixIndex].rgbBlue;dataOfBmp[index].rgbReserved = pRgb[mixIndex].rgbReserved;index++;}////////////////////////////////////////printf("%d个像素数据信息:\n",width*height); //输出像素信息///读完了信息,马上关闭,与fopen对应fclose(pfile);//int projectionOnX[500];int *projectionOnX = new int[width]; //用来存储投影量的整型数组int *projectionOnY = new int[height]; //用来存储投影量的整型数组for(int i=0;i<width;++i){projectionOnX[i]=0;}for(int i=0;i<height;++i){projectionOnY[i]=0;}//////////////////////////////////粗略显示图片for(int i=height-1;i>=0;--i){if(i%6==0)printf("\n");for(int j=0;j<width;++j){if(i%6==0 && j%6==0){int k = i*width + j;//int num=dataOfBmp[k].rgbRed;showRgbQuan(&dataOfBmp[k]);//if(dataOfBmp[k].rgbRed>0) projectionOnX[j]+=1;}}printf("\n\n<自上而下横向扫描>:\n"); printf("<水平方向投影分布>\n\n"); //水平X轴上投影投影值记录/////////////////////////////////for(int i=height-1;i>=0;--i){//if(i%6==0)printf("\n");for(int j=0;j<width;++j){int k = i*width + j;//int num=dataOfBmp[k].rgbRed;if(dataOfBmp[k].rgbRed>0){projectionOnX[j]+=1;projectionOnY[i]+=1;}//end if}//end for}//end for////////////////////////////////for(int i=height-1;i>=0;--i){//if(i%6==0)printf("\n");for(int j=0;j<width;++j){int k = i*width + j;//int num=dataOfBmp[k].rgbRed;if(dataOfBmp[k].rgbRed>0){if(i==(height-1) || i==0){if(projectionOnX[j]>(height*0.8)){ projectionOnX[j]=0;}}if(j==(width-1) || j==0){if(projectionOnY[i]>(width*0.8)){projectionOnY[i]=0;}}}//end if}//end for}//end for//求平均投影值//获得一个01分布数组double rateChar=0.75;int minNum=int((1-rateChar)*width); int *min=new int[minNum];for (int m=0;m<minNum;++m){min[m]=height;}int averageMin=0;int maxNum=int(rateChar*width);int *max=new int[maxNum];for (int m=0;m<maxNum;++m){max[m]=0;}int maxAll=0;int averageMax=0;//for(int i=0;i<width;++i)projectionOnX[i]=averageMax;for(int m=0;m<width;++m){for (int i=0; i<minNum-1; ++i){// printf("[%d]",s);if(projectionOnX[m] < min[i]) //判断插入的条件{for(int j=minNum-2; j>=i; --j){ //插入地址的元素依次向后移动一位,min[j+1]=min[j];}min[i]=projectionOnX[m];break; //已经判断到插入位置并移位,不必再判断}}for (int i=0; i<maxNum-1; ++i){if(projectionOnX[m] > max[i]) //判断插入的条件{for(int j=maxNum-2; j>=i; --j){ //插入地址的元素依次向后移动一位,max[j+1]=max[j];}max[i]=projectionOnX[m];break; //已经判断到插入位置并移位,不必再判断}}}for(int m=0;m<minNum;++m){minAll+=min[m];}averageMin=int(maxAll/maxNum);for(int m=0;m<maxNum;++m){maxAll+=max[m];}averageMax=int(maxAll/maxNum);printf("[maxNum=%d][minNum=%d][maxAll=%d][minAll=%d][maxAverage=%d]-[averageMin= %d]",maxNum,minNum,maxAll,minAll,averageMax,averageMin);//for(int c=averageMin;c<averageMax;++c){///////////////////////////////////////////~~90%for(int c=min[0];c<max[0];++c){//min to max//100%int *arrOneZero=new int[width];for(int m=0;m<width;++m){arrOneZero[m]=(projectionOnX[m]>c)?1:0;}//遍历projectionOnX[],寻找空白峰值作为切割位置int cutNum=20; //切割位置的数量CUT *cutData=new CUT[cutNum];int mark=0; //指示切割位置记录下标int countOne=0; //投影值为0的列数int preNum=arrOneZero[0]; //用以记录上一列的投影值int *cutPos=new int[cutNum];for(int i=0;i<cutNum;i++)cutPos[i]=-1; //如果坐标为-1,可以认为不在数组中for(int m=0;m<width;++m){int newNum=arrOneZero[m];if(newNum==preNum){if(newNum==1){countOne+=1;}}else{if(countOne>3) //width/10)//黑色部分,也就是字体投影应该大于车牌宽度的10%{//切割记录cutData[mark].left=m-countOne-1;cutData[mark].right=m;mark+=1;//进行插入,并保持排序,以下是计算优先程度,粗略的情况下可有可无for (int i=0; i<cutNum-1; ++i){int index=cutPos[i];int num=projectionOnX[m];// printf("[%d]",lastMid);if(index=-1 || num <= projectionOnX[index] ) //判断插入的条件,=-1可以认为极小,可以插入{for(int j=cutNum-2; j>=i; --j){ //插入地址的元素依次向后移动一位,cutPos[j+1]=cutPos[j];}cutPos[i]=m;break; //已经判断到插入位置并移位,不必再判断}}//end forfor (int i=0; i<cutNum-1; ++i){int index=cutPos[i];if(index==-1)break;int num=projectionOnX[m-countOne-1];// printf("[%d]",s);if(index==-1 || num <= projectionOnX[index] )//判断插入的条件{for(int j=cutNum-2; j>=i; --j){ //插入地址的元素依次向后移动一位,cutPos[j+1]=cutPos[j];}cutPos[i]=m-countOne-1;break;//已经判断到插入位置并移位,不必再判断}}}//end ifcountOne=1;}//end elsepreNum=newNum; //用完了当前投影,注意保存为下一投影值 }//end forif(mark<numOfCut){continue;}////////////////////////////////////////显示投影波形图和切割位置for(int m=0;m<width;++m){//if(projectionOnX[m]>height*0.2){for(int n=0;n<projectionOnX[m];n+=2){printf("#");}printf("[第%d列]",m);int cut=0;for(int k=0;k<cutNum;++k){if(m==cutPos[k]){cut+=1;printf("<----可能切割[%d]-%d",k,arrOneZero[m]);if(cut==2)break;}}printf("\n");}/////////////////////////////////////printf("\n\n<自左向右竖向扫描>:\n");printf("<垂直方向投影分布>\n\n");int allOnY=0;int averageY=0;int *arrY=new int[height];for(int m=0;m<height;++m){arrY[m]=0;allOnY+=projectionOnY[m];}averageY=allOnY/height;int cutY[2]={0,height-1};int countY=0;for(int m=0;m<height;++m){arrY[m]=projectionOnY[m]>(averageY*3/4)?1:0; }//for(int i=0;i<height;++i)projectionOnY[i]=0;int preY=arrY[0];for(int m=0;m<height;++m){int newY=arrY[m];if(newY==preY){if(arrY[m]==1){countY+=1;}}else{if(countY>int(height*0.3)){cutY[0]=m-countY-1;////////////BUGER2010.8 cutY[1]=m;/////////////////////break;}countY=1;}preY=newY;}////////////显示for(int m=0;m<height;++m){for(int n=0;n<projectionOnY[m];n+=2){printf("#");}printf("[第%d行]",m);int cut=0;for(int k=0;k<2;++k){if(m==cutY[k]){cut+=1;printf("<----可能切割[%d]",k);if(cut==2)break;}}printf("\n");}///////////////////////////////////////////int unposible=0;int widthAverage=(cutData[numOfCut-1].right-cutData[0].left)/numOfCut;for(int m=0;m<mark;++m){cutData[m].no=m;cutData[m].up=cutY[1];cutData[m].down=cutY[0];int w=cutData[m].right-cutData[m].left;if(w>widthAverage){ //有人太穷,有人太富unposible+=(numOfCut-1);if(m==0){cutData[m].left=cutData[m].right-int(widthAverage*3/4);}if(m==(numOfCut-1)){cutData[m].right=cutData[m].left+int(widthAverage*3/4);}//break;}if(w<(widthAverage/3)){unposible+=1;}}if(unposible>numOfCut){continue;}printf("\n\n\n\n<切割位置显示:>\n\n");for(int m=0;m<mark;++m){MakeBmpHeader(strFile,dataOfBmp,width,cutData[m]);printf("切割[%d]--< 上%d,下%d,左%d,右%d >\n",m,cutData[m].up,cutData[m].down,cutData[m].left,cutData[m].right);}/////////printf("\n\n\n\n");/////break;}//////////////////////////////end for form min to maxfclose(pfile);if(bitInfoHead.biBitCount<24)free(pRgb);free(dataOfBmp);free(pColorData);printf("New File...\n");return ;}//***主应用程序int _tmain(int argc, _TCHAR* argv[]){char strfile[50];while(true){printf("Please input the .bmp file name:\n"); scanf("%s",strfile);DealFile(strfile,7);}return 0;}。