2024年汽车车牌识别系统实现(三)-- 车牌矫正+字符分割+代码实现(2),想进BTAJ

最后

分享一些资料给大家,我觉得这些都是很有用的东西,大家也可以跟着来学习,查漏补缺。

《Java高级面试》

《Java高级架构知识》

《算法知识》

本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

需要这份系统化的资料的朋友,可以点击这里获取

在这里插入图片描述

给定原始图像的四个顶点坐标和变换后图像的四个顶点坐标,即可求得变换矩阵。求得变换矩阵后,需要求出倾斜状态下车牌的四个顶点坐标,具体步骤如下:首先定位出车牌位置,判断车牌是否倾斜。车牌倾斜主要有逆时针倾斜和顺时针倾斜的两种情况。本文只说明逆时针倾斜情况。逆、顺时针情况可以简化成如图3-2和图3-3的模型。

在这里插入图片描述

如图3-1所示,根据求得A、E、F、G的坐标(Top_Point、Right_Point、Bottom_Point、Left_Point),在图3-2中,则是根据▲ABC~▲ADE来计算出A、E、F、G点的坐标。本文只说明图3-1中G点的求解步骤如下:

求解G点的横坐标,如式(3-4)所示:

在这里插入图片描述

依据三角形相似原理,写出相似等式,如式(3-5)所示:

在这里插入图片描述

求解得到G的纵坐标值,如式(3-6)所示:

在这里插入图片描述

求解后,原始图像中车牌的4个顶点均已知。根据上文车牌特征分析可知,车牌尺寸为440×140,故变换后的车牌4个顶点依次为(0,140)、(440,0)、(0,0)、 (440,140)。根据变换矩阵与变换前后对应顶点关系,利用透视变换倾斜纠正算法对车牌进行矫正,矫正前后实验结果分别如图3-4和图3-5所示。

在这里插入图片描述

三、跳变次数法去除车牌边框和铆钉


在这里插入图片描述

车牌倾斜矫正之后,车牌边框和用于固定车牌的铆钉会影响字符分割操作的结果,因此,去除车牌边框和铆钉是车牌字符分割算法能否取得成功的关键步骤。本文采用跳变次数法[5][6]去除边框和铆钉。跳变次数法去除边框及铆钉的原理及流程如图3-6。

在这里插入图片描述

由于字符颜色与车牌底色不同,因此车牌区域中存在大量的颜色突变信息,这就为跳变次数法的实施创造了条件。所谓的跳变是指由字符区域过渡到非字符区域或者由非字符区域过渡到字符区域。具体做法是从上至下扫描出二值化后的车牌图像,找到跳变次数超过预先设定阈值的第一行,且之后连续3行跳变次数均超过阈值,则认定该行为车牌字符上边界;同理,从下至上扫描车牌图像,找到突变次数超过预先设定阈值的一行,且之后连续3行突变次数均超过阈值,则该行为车牌字符下边界。在确定车牌上下边界的前提下,接着确定车牌字符的左边界、右边界。因为车牌中可能存在数字1,数字1的跳变次数为2,为了防止滤除掉阿拉伯数字1,设定跳变次数的阈值为2。具体做法是从左至右扫描车牌图像,依次统计每列的跳变次数。找到跳变次数超过阈值的第一行,且之后连续3列跳变次数均超过阈值,则该行为车牌字符左边界;同理,找到车牌字符右边界。去除前后效果分别如图3-8和图3-9所示。

在这里插入图片描述

四、字符细化操作


去除边框及铆钉后,图像上仍有一些残留的噪声点,这些残留的噪声点会对垂直投影法划分字符操作产生不良影响。因此,对去除边框和铆钉后的图像进行形态学腐蚀处理是非常有必要而且是至关重要的,腐蚀处理在去掉车牌字符区域残留噪声的同时,也可以对字符进行细化,形态学腐蚀处理效果如图3-10所示。

在这里插入图片描述

五、垂直投影法分割字符


在这里插入图片描述

去除边框、铆钉,以及对字符进行细化处理后,接下来需要将车牌字符区域划分为单个字符。本文采取基于垂直投影法的字符划分方法[7][8]来划分车牌字符区域,依据车牌特点可知,每个字符之间都存在一定的纯黑区域。二值化后,字符区域为白色,车牌中的非字符区域为黑色。

划分单个字符的原理及具体流程如图3-11所示。首先计算每列中白色像素点个数,垂直投影后得到直方图,如图3-12所示,并以此来判断各个字符的起始位置。然后从左至右扫描投影直方图,找到存在白色像素点的第一列,则认定为该列是车牌第一个字符的左边界。若上一列存在白色像素点,而下一列是不存在白色像素点的黑色区域,则认定该列为第一个字符的右边界,同理,便可分割出其余6个车牌字符左右边界。投影得到的图像如图3-12所示,划分出的单个字符如图3-13所示。

在这里插入图片描述

六、字符图像归一化处理


由于从采集图像中提取出的车牌大小不完全相同,这就导致了划分出来的单个字符的尺寸可能不同,为了能够适应已经训练好的车牌字符识别网络,需要对划分出的单个车牌字符进行归一化处理,使得从采集图像中定位出的车牌在字符分割操作完成后,所获取的车牌单个字符图像大小都为20_20像素[2],如图3-11所示。这里至于为什么都归一化为20_20像素,是因为我的神经网络的输入都是20*20像素的。

在这里插入图片描述

七、代码实现


for rect in car_contours:

rect = (rect[0], (rect[1][0]+20, rect[1][1]+5), rect[2])

box = cv2.boxPoints(rect)

#图像矫正 cv2.getAffineTransform(pos1,pos2),其中两个位置就是变换前后的对应位置关系。输出的就是仿射矩阵M,最后这个矩阵会被传给函数 cv2.warpAffine() 来实现仿射变换

if rect[2] > ANGLE: #正角度

new_right_point_x = vertices[0, 0]

new_right_point_y = int(vertices[1, 1] - (vertices[0, 0] - vertices[1, 0]) / (vertices[3, 0] - vertices[1, 0]) * (vertices[1, 1] - vertices[3, 1]))

new_left_point_x = vertices[1, 0]

new_left_point_y = int(vertices[0, 1] + (vertices[0, 0] - vertices[1, 0]) / (vertices[0, 0] - vertices[2, 0]) * (vertices[2, 1] - vertices[0, 1]))

point_set_1 = np.float32([[440, 0], [0, 0], [0, 140], [440, 140]])

elif rect[2] < ANGLE: #负角度

new_right_point_x = vertices[1, 0]

new_right_point_y = int(vertices[0, 1] + (vertices[1, 0] - vertices[0, 0]) / (vertices[3, 0] - vertices[0, 0]) * (vertices[3, 1] - vertices[0, 1]))

new_left_point_x = vertices[0, 0]

new_left_point_y = int(vertices[1, 1] - (vertices[1, 0] - vertices[0, 0]) / (vertices[1, 0] - vertices[2, 0]) * (vertices[1, 1] - vertices[2, 1]))

point_set_1 = np.float32([[0, 0], [0, 140], [440, 140], [440, 0]])

new_box = np.array([(vertices[0, 0], vertices[0, 1]), (new_left_point_x, new_left_point_y), (vertices[1, 0], vertices[1, 1]),(new_right_point_x, new_right_point_y)])

point_set_0 = np.float32(new_box)

mat = cv2.getPerspectiveTransform(point_set_0, point_set_1)

dst = cv2.warpPerspective(img, mat, (440, 140))

cv_show(‘dst’,dst)

#-------------------------------字符分割-------------------------------------

plate_original = dst.copy()

img_aussian = cv2.GaussianBlur(dst,(5,5),1)

cv_show(‘img_aussian’,img_aussian)

#中值滤波

dst = cv2.medianBlur(img_aussian,3)

对车牌进行精准定位

img_B = cv2.split(dst)[0]

img_G = cv2.split(dst)[1]

img_R = cv2.split(dst)[2]

for i in range(dst.shape[:2][0]):

for j in range(dst.shape[:2][1]):

if abs(img_B[i,j] - Blue) < THRESHOLD and abs(img_G[i,j] - Green) <THRESHOLD and abs(img_R[i,j] - Red) < THRESHOLD:

dst[i][j][0] = 0

dst[i][j][1] = 0

dst[i][j][2] = 0

else:

dst[i][j][0] = 255

dst[i][j][1] = 255

dst[i][j][2] = 255

cv_show(‘dst’,dst)

灰度化

gray = cv2.cvtColor(dst, cv2.COLOR_BGR2GRAY)

cv_show(‘gray’,gray)

#-------------------------------跳变次数去掉铆钉和边框----------------------------------

times_row = [] #存储哪些行符合跳变次数的阈值

for row in range(LICENSE_HIGH): # 按行检测 白字黑底

pc = 0

for col in range(LICENSE_WIDTH):

if col != LICENSE_WIDTH-1:

if gray[row][col+1] != gray[row][col]:

pc = pc + 1

times_row.append(pc)

print(“每行的跳变次数:”,times_row)

#找车牌的下边缘-从下往上扫描

row_end = 0

row_start = 0

for row in range(LICENSE_HIGH-2):

if times_row[row] < 16:

continue

elif times_row[row+1] < 16:

continue

elif times_row[row+2] < 16:

continue

else:

row_end = row + 2

print(“row_end”,row_end)

#找车牌的上边缘-从上往下扫描

i = LICENSE_HIGH-1

row_num = [] #记录row_start可能的位置

while i > 1:

if times_row[i] < 16:

i = i - 1

continue

elif times_row[i-1] < 16:

i = i - 1

continue

elif times_row[i-2] < 16:

i = i - 1

continue

else:

row_start = i - 2

row_num.append(row_start)

i = i - 1

print(“row_num”,row_num)

#确定row_start最终位置

for i in range(len(row_num)):

if i != len(row_num)-1:

if abs(row_num[i] - row_num[i+1])>3:

row_start = row_num[i]

print(“row_start”,row_start)

times_col = [0]

for col in range(LICENSE_WIDTH):

pc = 0

for row in range(LICENSE_HIGH):

if row != LICENSE_HIGH-1:

if gray[row,col] != gray[row+1,col]:

pc = pc + 1

times_col.append(pc)

print(“每列的跳变次数”,times_col)

找车牌的左右边缘-从左到右扫描

col_start = 0

col_end = 0

for col in range(len(times_col)):

最后

分布式技术专题+面试解析+相关的手写和学习的笔记pdf

还有更多Java笔记分享如下:

image

本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

需要这份系统化的资料的朋友,可以点击这里获取

in range(len(times_col)):

最后

分布式技术专题+面试解析+相关的手写和学习的笔记pdf

还有更多Java笔记分享如下:

[外链图片转存中…(img-0HWDDSM0-1715263501942)]

本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

需要这份系统化的资料的朋友,可以点击这里获取

  • 5
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 这是一个非常有趣的项目,下面是一个基于MATLAB的车牌识别系统设计的程序,包括字符模板和车牌识别。在这个程序中,我们使用了经典的模板匹配方法来识别车牌字符。 首先,我们需要准备一些训练数据,即字符模板。这些字符模板是用来训练我们的系统,以便于识别车牌上的字符。在这个程序中,我们使用了一个包含26个大写字母和10个数字的字符集。 接着,我们需要将这些字符模板转换成二进制图像。这可以通过使用MATLAB的im2bw函数来实现。这个函数将把灰度图像转换成二值图像,其中1表示前景,0表示背景。 接下来,我们需要计算一些特征,即每个字符模板的Hu矩。这些Hu矩是一组用于描述图像形状的数学特征。在MATLAB中,我们可以使用函数“hu_moments”来计算这些特征。 一旦我们有了这些字符模板和它们的特征,我们就可以使用它们来识别车牌上的字符。具体来说,我们可以使用模板匹配方法。在这个方法中,我们将车牌图像中的每个字符与我们的字符模板进行比较,并找到最匹配的模板。我们可以使用MATLAB的corr2函数来计算两个图像的相关性,并找到最相关的模板。 最后,我们可以将识别的字符组合在一起,从而得到完整的车牌号码。这个程序的完整代码如下所示: ### 回答2: MATLAB车牌识别系统设计中的字符模板是一种用于自动识别车牌字符的关键组成部分。这个字符模板是一个基于MATLAB程序的系统,它利用图像处理和模式识别技术来实现车牌字符的自动识别。 首先,我们需要建立一个车牌字符的数据库。这个数据库包含了所有可能的车牌字符样本,比如数字和字母等。这些字符样本需要通过图像采集设备获取,并进行预处理,如灰度化、二值化和字符分割等。然后,我们将这些处理后的字符样本存储在数据库中以备后续使用。 接下来,我们需要设计一个字符模板匹配算法。这个算法的目的是将输入的车牌图像与字符模板进行比对,并找出最匹配的字符样本。在这个算法中,我们首先需要对输入的车牌图像进行与数据库中字符样本相同的预处理,并进行字符分割。然后,我们将预处理后的字符字符模板进行比对,计算相似度,并找到最匹配的字符。 最后,我们将识别到的字符输出到车牌识别系统的结果中,完成整个字符识别过程。这样,我们就能够通过这个基于MATLAB的车牌识别系统自动识别出车牌中的字符信息了。 总的来说,MATLAB车牌识别系统设计中的字符模板是通过建立字符样本数据库,并设计字符模板匹配算法实现的。这个字符模板在车牌识别系统中扮演着重要的角色,能够准确快速地对输入的车牌图像中的字符进行自动识别,提高了车牌识别系统的效率和准确率。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值