基于车牌形状和颜色的车牌定位
车牌识别的学习和车牌定位的实验
- 车牌识别算法综述
- 基于形状和颜色的车牌定位
- 第一步:去噪,二值化
- 第二步:边缘检测,开运算和闭运算
- 第三步:颜色筛选出车牌区域
- 车牌矫正
- 字符分割
- 字符识别
车牌识别算法综述
前言:近年来,人工智能的研究不断深入,智慧城市,智慧交通也引起了大家的关注,车牌识别作为智慧交通的重要一环,被广泛应用在:停车场管理,违章处理,高速收费等领域。
同时也随着新能源汽车的不断增多,原来识别普通汽车7字符车牌的车牌识别系统需要增加识别新能源汽车8字符车牌的功能。车牌识别主要分为四个步骤:车牌定位,车牌矫正,字符分割和字符识别。
车牌定位:在一张含有车牌的图片中找到车牌区域。主要由三个方向的方法:
一、基于特征的算法,如基于颜色特征和边缘特征的算法,基于字符边缘的算法,就是找到内部有很多竖直边缘的矩阵块(在车牌不倾斜的情况下才有用)
二、基于数学形态学的算法,主要要用到闭运算,开运算,再根据车牌比例进行筛选。
三、基于机器学习方法的算法,涉及分类,回归,训练等问题。如基于SVM的车牌定位算法、基于遗传算法的定位算法,基于神经网络的车牌定位算法。
车牌矫正:基本原理都是找到与车牌方位相互契合的一条直线,求出该直线的角度,即为需要调整的角度。
一、Hough变换
利用Hough变换提取直线是一种变换域提取直线的方法,它把直线的坐标,变换到过点的直线的系数域,利用了共线和直线相交的关系。
将x-o-y坐标上的各字符对应的像素点变到s-o-θ平面上(利用公式s=xcosθ+ysinθ),把s-o-θ平面分成网格状,每个小网格对应一个计数矩阵,当有一条曲线经过该网格就加一,最后数值最大的网格对应原始图像中最长的直线。(因为计数矩阵元素的值等于共线的点数)求出最大数值网格对应的列坐标θ,倾斜角为90度-θ。根据这个角度进行旋转。
二、Radon变换
我们知道一条直线在法线方向的投影最大。所以我们首先通过边缘检测找出原图的直线,再对这些直线在0-179度范围内做投影(此时就是Radon变换),峰值最大的方向θ就是直线的法线方向,所以直线的倾斜角度就是90度-θ。
三、线性回归方法
根据点的分布找到一条使所有点到这条直线的欧式距离的和最小,一般用最小二乘法来拟合直线,然后确定好这条直线的角度,根据这条直线的角度来调整图片角度。
四、两点法
在使用最小二乘法时,我们已经检测到图像与背景交线的一系列坐标点,这些点近似分布在一条直线上,取多对点求直线的斜率,再取平均值,从而确定倾角。
字符分割:主要有以下三种:
一、投影法:在水平、竖直方法统计字符像素个数,没有像素的地方就是间隔处。
二、连通域分割:每次扫描二值化图像的N个像素点,统计出字符像素点的个数来确定字符部分的连通域。数字,字母一般是单连通域,汉字字符一般是多连通域,所以先确定数字,字母字符,然后剩下的字符就是汉族字符。
三、基于静态边界的方法:需要在车牌定位非常精准的前提下,缩放图片至固定尺寸,结合车牌的长宽比以及字符间距等特点,判断出每个字符的位置。
字符识别:主要有三种方向:
一、基于模板匹配算法:分为基于特征提取的模板匹配方法和基于灰度值匹配法,前者涉及大量数学形态学计算,计算复杂。后者有标准库,必须要与模板库同大小,同字体才能达到好的效果。
二、基于特征统计的字符识别:这个特征包括:外部轮廓,内部结构和笔画变换等等,如提取13维的像素特征。缺点:汉字需要提取的特征较多,计算量大。受车牌分割准确性及噪声的影响。
三、基于机器学习的方法:如基于SVM的字符识别,基于神经网络的字符识别。
基于形状和颜色的车牌定位
这一步要做的就是对输入的一张含有车牌的彩色图片,找到我们要的车牌区域
第一步:去噪,二值化
将得到彩色图片进行高斯去噪,变成灰度图,然后再变成二值图像。
#高斯去噪if blur > 0:img = cv2.GaussianBlur(img, (blur, blur), 0)#图片分辨率调整 oldimg = img #oldimg是经过高斯模糊的原图,后面还会用到。img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)#找到图像边缘ret, img_thresh = cv2.threshold(img_opening, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU) #转化为二值图像#cv2.imshow("binary_img", img_thresh)
第二步:边缘检测,开运算和闭运算
对二值图像进行canny边缘检测,然后用形态学的开运算和闭运算合并边缘围起来的区域,筛选出宽高比在2-5.5之间的矩形。(虽然标准的车牌宽是440mm,高是140mm,比例是3.1,但是我们考虑到照相角度的问题,我们将范围扩大到2-5.5避免漏掉车牌区域,当然这会造成其他不是车牌的矩形区域入选,但我们可以在后面用颜色特征,排除掉这些非车牌区域。)
# canny边缘检测
img_edge = cv2.Canny(img_thresh, 100, 200)
#cv2.imshow("canny_img", img_edge)
#cv2.waitKey(0)
#使用开运算和闭运算让图像边缘成为一个整体
kernel = np.ones((self.cfg["morphologyr"], self.cfg["morphologyc"]), np.uint8)
img_edge1 = cv2.morphologyEx(img_edge, cv2.MORPH_CLOSE, kernel)
img_edge2 = cv2.morphologyEx(img_edge1, cv2.MORPH_OPEN, kernel)
用矩形框,框出各区域,将矩形框的长宽比在2-5.5之间的标记出来。
#查找图像边缘整体形成的矩形区域,可能有很多,车牌就在其中一个矩形区域中try:contours, hierarchy = cv2.findContours(img_edge2, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) #contours包括图片所有的轮廓,每个轮廓又包含四个顶点坐标except ValueError:#python3是返回三个参数image, contours, hierarchy = cv2.findContours(img_edge2, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)contours = [cnt for cnt in contours if cv2.contourArea(cnt) > Min_Area] #筛选出点集区域大于最小面积的边缘,保存到contours里面print('边框所围区域大于最小面积的边框个数', len(contours))#一一排除不是车牌的矩形区域car_contours = []for cnt in contours:rect = cv2.minAreaRect(cnt) #求出边缘的最小外切矩形,rect包含:中心点,(长边,短边),旋转角度area_width, area_height = rect[1]if area_width < area_height:area_width, area_height = area_height, area_width #保证宽一定是长的那条边。wh_ratio = area_width / area_height #求出外切矩形的宽长比#要求矩形区域长宽比在2到5.5之间,2到5.5是车牌的长宽比,其余的矩形排除if wh_ratio > 2.0 and wh_ratio < 5.5:car_contours.append(rect)box = cv2.boxPoints(rect)box = np.int0(box)print("宽高比:",wh_ratio)print('宽长比在2~5.5之间的边框个数',len(car_contours))
第三步:颜色筛选出车牌区域
用颜色排除非车牌区域,把rbg格式的图片变成hsv格式的图片,因为hsv的图片能更好的区分出色彩。
关于HSV的介绍:
①H表示色调:用角度度量,取值范围为0°~360°,从红色开始按逆时针方向计算,红色为0°,绿色为120°,蓝色为240°。它们的补色是:黄色为60°,青色为180°,品红为300°;色调是人眼对光波长的认知,一旦颜色从一种颜色进入另一种颜色,人眼将会立即发现。
②S表示饱和度:饱和度表示颜色的纯净度,取值范围为0.0~1.0
③V 表示亮度:取值范围0~255,0是黑色,255是白色
黄色色相11-34,饱和度大于34,绿色色相35-99,饱和度大于34,黄色色相100-124,饱和度大于34。
黑色的亮度0-46,白色的亮度221-225。
我们将长宽比满足要求的矩形区域进行颜色统计,如果像素中色相为黄绿蓝中任意颜色的像素个数大于矩形区域总像素的一半,就判断为车牌颜色,所以该矩形是车牌区域,而当黑色+白色像素个数大于0.7倍的矩形区域总像素,则判断为背景。
#开始使用颜色定位,排除不是车牌的矩形,目前只识别蓝、绿、黄车牌
colors = []
for card_index,card_img in enumerate(card_imgs):green = yello = blue = black = white = 0card_img_hsv = cv2.cvtColor(card_img, cv2.COLOR_BGR2HSV)#有转换失败的可能,原因来自于上面矫正矩形出错if card_img_hsv is None:continuerow_num, col_num= card_img_hsv.shape[:2]card_img_count = row_num * col_numfor i in range(row_num):for j in range(col_num):H = card_img_hsv.item(i, j, 0)S = card_img_hsv.item(i, j, 1)V = card_img_hsv.item(i, j, 2)if 11 < H <= 34 and S > 34:#图片分辨率调整yello += 1elif 35 < H <= 99 and S > 34:#图片分辨率调整green += 1elif 99 < H <= 124 and S > 34:#图片分辨率调整blue += 1if 0 < H <180 and 0 < S < 255 and 0 < V < 46:black += 1elif 0 < H <180 and 0 < S < 43 and 221 < V < 225:white += 1color = "no"limit1 = limit2 = 0if yello*2 >= card_img_count:color = "yello"limit1 = 11limit2 = 34#有的图片有色偏偏绿elif green*2 >= card_img_count:color = "green"limit1 = 35limit2 = 99elif blue*2 >= card_img_count:color = "blue"limit1 = 100limit2 = 124#有的图片有色偏偏紫elif black + white >= card_img_count*0.7:#TODOcolor = "bw"print(color)colors.append(color)print("blue,green,yello,black,white,card_img_count:")print(blue, green, yello, black, white, card_img_count)#cv2.imshow("color", card_img)#cv2.waitKey(0)if limit1 == 0:continue #说明是背景图#以上为确定车牌颜色#以下为根据车牌颜色再定位,缩小边缘非车牌边界xl, xr, yh, yl = self.accurate_place(card_img_hsv, limit1, limit2, color)if yl == yh and xl == xr:continueneed_accurate = Falseif yl >= yh:yl = 0yh = row_numneed_accurate = Trueif xl >= xr:xl = 0xr = col_numneed_accurate = Truecard_imgs[card_index] = card_img[yl:yh, xl:xr] if color != "green" or yl < (yh-yl)//4 else card_img[yl-(yh-yl)//4:yh, xl:xr]if need_accurate:#可能x或y方向未缩小,需要再试一次card_img = card_imgs[card_index]card_img_hsv = cv2.cvtColor(card_img, cv2.COLOR_BGR2HSV)xl, xr, yh, yl = self.accurate_place(card_img_hsv, limit1, limit2, color)if yl == yh and xl == xr:continueif yl >= yh:yl = 0yh = row_numif xl >= xr:xl = 0xr = col_numcard_imgs[card_index] = card_img[yl:yh, xl:xr] if color != "green" or yl < (yh-yl)//4 else card_img[yl-(yh-yl)//4:yh, xl:xr]
车牌矫正
因为拍摄角度的原因,我们可能得到像下图这样,倾斜的车牌,如果不进行倾斜矫正的话,不利于后面的字符分割和字符识别。车牌矫正可以利用线,也可以利用点,利用线就是找到符合车牌走向的直线,获得这个直线的斜率,得到倾斜角度,再把车牌旋转这么多角度就行了。利用点的话就有仿射变换。
我们可以利用放射变换来矫正车牌角度。利用变换前后矩形四个顶点的坐标变换,得到变换矩阵M,利用这个M完成选定区域的仿射变换。
box = cv2.boxPoints(rect)heigth_point = right_point = [0, 0]
left_point = low_point = [pic_width, pic_hight]
for point in box:if left_point[0] > point[0]:left_point = pointif low_point[1] > point[1]:low_point = pointif heigth_point[1] < point[1]:heigth_point = pointif right_point[0] < point[0]:right_point = pointif left_point[1] <= right_point[1]:#正角度new_right_point = [right_point[0], heigth_point[1]]pts2 = np.float32([left_point, heigth_point, new_right_point])#字符只是高度需要改变pts1 = np.float32([left_point, heigth_point, right_point])M = cv2.getAffineTransform(pts1, pts2)dst = cv2.warpAffine(oldimg, M, (pic_width, pic_hight))point_limit(new_right_point)point_limit(heigth_point)point_limit(left_point)card_img = dst[int(left_point[1]):int(heigth_point[1]), int(left_point[0]):int(new_right_point[0])]card_imgs.append(card_img)#cv2.imshow("card", card_img)#cv2.waitKey(0)elif left_point[1] > right_point[1]:#负角度new_left_point = [left_point[0], heigth_point[1]]pts2 = np.float32([new_left_point, heigth_point, right_point])#字符只是高度需要改变pts1 = np.float32([left_point, heigth_point, right_point])M = cv2.getAffineTransform(pts1, pts2)dst = cv2.warpAffine(oldimg, M, (pic_width, pic_hight))point_limit(right_point)point_limit(heigth_point)point_limit(new_left_point)card_img = dst[int(right_point[1]):int(heigth_point[1]), int(new_left_point[0]):int(right_point[0])]card_imgs.append(card_img)
字符分割
一般都采用直方图统计的方法,水平方向统计,得到字符的上边缘和下边缘,垂直方向统计得到字符的左边缘,右边缘。
#查找水平直方图波峰
x_histogram = np.sum(gray_img, axis=1)
x_min = np.min(x_histogram)
x_average = np.sum(x_histogram)/x_histogram.shape[0]
x_threshold = (x_min + x_average)/2
wave_peaks = find_waves(x_threshold, x_histogram)
if len(wave_peaks) == 0:print("peak less 0:")continue
#认为水平方向,最大的波峰为车牌区域
wave = max(wave_peaks, key=lambda x:x[1]-x[0])
gray_img = gray_img[wave[0]:wave[1]]
#查找垂直直方图波峰
row_num, col_num= gray_img.shape[:2]
#去掉车牌上下边缘1个像素,避免白边影响阈值判断
gray_img = gray_img[1:row_num-1]
y_histogram = np.sum(gray_img, axis=0)
y_min = np.min(y_histogram)
y_average = np.sum(y_histogram)/y_histogram.shape[0]
y_threshold = (y_min + y_average)/5#U和0要求阈值偏小,否则U和0会被分成两半wave_peaks = find_waves(y_threshold, y_histogram)
字符识别
一般都是用SVM,用别人训练好的数据集SVM.dat,因为不知道怎么训练参数,呜呜呜。。。
基于车牌形状和颜色的车牌定位相关推荐
- matlab hough算法车牌识别,一种基于数学形态学和Hough变换的车牌图像检测及定位算法-汽车电子-与非网...
车牌识别系统(LPR)在现代交通检测和管理部门中发挥着举足轻重的作用.车牌识别系统主要包括车牌定位.字符分割和字符识别三部分[1].由于车牌定位的准确与否将会直接影响到车牌识别的结果,因此,车牌定位是 ...
- matlab中caitu_tiqu,Matlab平台基于颜色的车牌识别程序
Matlab平台基于颜色的车牌识别程序 matlab 2020-11-18 下载地址 https://www.codedown123.com/51252.html Matlab平台基于颜色的车牌识别程 ...
- mser python车牌识别_基于MSER与SVM算法的车牌定位识别方法
基于 MSER 与 SVM 算法的车牌定位识别方法 胡成伟 ; 袁明辉 [期刊名称] <软件> [年 ( 卷 ), 期] 2020(041)002 [摘要] 针对实际车牌识别系统中车牌位置 ...
- 基于MATLAB图像处理的恶劣天气自动车牌识别
基于MATLAB图像处理的恶劣天气自动车牌识别系统设计 摘要 针对恶劣天气环境下传统的自动车牌识别系统存在运行时间长.输出车牌信息不准等问题,本文提出了借助MATLAB的图像处理功能从图像去雾.车牌定 ...
- 【车牌识别】RGB颜色模型车牌识别【含GUI Matlab源码 888期】
⛄一.车牌识别简介 1 车牌图像处理 车牌图像处理主要有五个组成部分:图像灰度化.图像二值化.图像边缘检测.图像形态学运算和图像滤波处理.它是车牌识别系统中最根本且最基础的操作,车牌图像处理的好坏情况 ...
- 数字图像处理——大作业 基于车道信息的违法车辆车牌识别
数字图像处理--大作业 基于车道信息的违法车辆车牌识别 一.车牌识别研究现状与分析 二.车牌识别算法原理 2.1 车牌定位 2.1.1 基于RGB阈值的车牌区域初定位 2.1.2 基于数学形态学的车牌 ...
- 基于Opencv的开源的中文车牌识别系统
真正的大师,永远都怀着一颗学徒的心! 一.项目简介 基于Opencv的开源的中文车牌识别系统. 二.实现功能 车牌定位 车牌判断 车牌监测 字符分割 字符鉴别 字符识别 车牌识别 车牌抽象 训练车牌识 ...
- 基于tensorflow2.1和opencv的车牌识别系统
系列文章目录 这个是最近参加比赛,要做的车牌识别系统,单单对车牌识别,不用对车牌进行定位. 用opencv的截图功能,将每一个字符分割下来,然后放入神经网络进行特征提取. 大致内容 1.制作数据集 2 ...
- (结构体+指针)定义“车”结构体,实现改变车颜色,车牌操作
简易的代码,只有2个功能,修改车颜色和车牌,保存退出. 方法一 #include<stdio.h> #include <stdlib.h> int n; typedef str ...
- 【深度学习实践】基于深度学习的车牌识别(python,车牌检测+车牌识别)
车牌识别具有广泛的应用前景,基于传统方法的车牌识别效果一般比较差,随着计算机视觉技术的快速发展,深度学习的方法能够更好的完成车牌识别任务. 本文提供了车牌识别方案的部署链接,您可以在网页上体验该模型的 ...
最新文章
- 内存四域,变量声明和定义,寄存器,c内嵌汇编,auto,堆栈,常量,静态变量
- cacls文件服务器备份与恢复,实战安全设置WEB专用服务器技巧
- 推荐系统遇上深度学习(八)--AFM模型理论和实践
- MFCC梅尔频率倒谱系数
- tf.Variable,tf.get_variable,tf.variable_scope,tf.name_scope区别分析
- 吴恩达老师的机器学习和深度学习课程笔记打印版(全)
- 四二拍用音符怎么表示_2020圣诞平安夜怎么发朋友圈?朋友圈关于平安夜经典语录精选...
- 神经网络训练ai玩游戏,人工神经网络入门
- 铜陵学院计算机程序设计大赛,ACM程序设计大赛
- 论坛——迪文屏常用操作
- 《知识产权知识产权信用管理规定》解读问答
- 基于AMSR-E和AMSR2数据的全球长时序日尺度土壤水分数据集(2002-2022)
- java服务端用到的javase的基础知识_javase基础篇知识归纳
- 一元二次方程虚根求法java_一元二次方程课件ppt
- 计算机提示找不到系统文件,为何我的电脑一开机就显示Windows找不到文件
- Python之Flask入门教程
- jQuery小型mp3音乐播放器插件
- PCB电路设计的14个误区
- 暑假假期训练总结-8
- OpenCV—画出时钟并动态同步系统时间