计算机视觉:使用opencv实现车牌识别
1 引言
汽车车牌识别(License Plate Recognition)是一个日常生活中的普遍应用,特别是在智能交通系统中,汽车牌照识别发挥了巨大的作用。汽车牌照的自动识别技术是把处理图像的方法与计算机的软件技术相连接在一起,以准确识别出车牌牌照的字符为目的,将识别出的数据传送至交通实时管理系统,以最终实现交通监管的功能。在车牌自动识别系统中,从汽车图像的获取到车牌字符处理是一个复杂的过程,主要分为四个阶段:图像获取、车牌定位、字符分割以及字符识别。目前关于车牌识别的算法有很多,本文基于opencv构建了车牌识别的整个流程,供大家学习参考。
1 车牌识别概述
1.1 opencv介绍
OpenCV的全称是:Open Source Computer Vision Library。OpenCV是一个基于开源发行的跨平台计算机视觉库,可以运行在Linux、Windows和Mac OS操作系统上。它轻量级而且高效——由一系列 C 函数和少量 C++ 类构成,同时提供了Python、Ruby、MATLAB等语言的接口,实现了图像处理和计算机视觉方面的很多通用算法。
1.2 车牌识别分解
车牌辨认的整个过程,可以拆解为以下三个步骤:
- 车牌定位: 第一步是从轿车上检测车牌地点方位。本文将运用OpenCV中矩形的边框检测来找到车牌位置。
- 字符切割:检测到车牌后,使用opencv将其裁剪并保存为新的图片,用于后续识别。
- 字符辨认: 在新的图片运用光学字符识(OCR)技术,提取图片中的文字、字符、数字。
2 车牌识别的实现
2.1 车牌定位
我国的汽车牌照一般由七个字符和一个点组成,车牌字符的高度和宽度是固定的,分别为90mm和45mm,七个字符之间的距离也是固定的12mm,点分割符的直径是10mm,字符间的差异可能会引起字符间的距离变化。
在民用车牌中,字符的排列位置遵循以下规律:
- 第一个字符通常是我国各省区的简称,用汉字表示;
- 第二个字符通常是发证机关的代码号,最后五个字符由英文字母和数字组合而成,字母是二十四个大写字母(除去I和O这两个字母)的组合,数字用"0-9"之间的数字表示。
从图像处理角度看,汽车牌照有以下几个特征:
- 第一个特征是是车牌的几何特征,即车牌形状统一为长宽高固定的矩形;
- 第二个特征是车牌的灰度分布呈现出连续的波谷-波峰-波谷分布,这是因为我国车牌颜色单一,字符直线排列;
- 第三个特征是车牌直方图呈现出双峰状的特点,即车牌直方图中可以看到双个波峰;
- 第四个特征是车牌具有强边缘信息,这是因为车牌的字符相对集中在车牌的中心,而车牌边缘无字符,因此车牌的边缘信息感较强;
- 第五个特征是车牌的字符颜色和车牌背景颜色对比鲜明。目前,我国国内的车牌大致可分为蓝底白字和黄底黑字,特殊用车采用白底黑字或黑底白字,有时辅以红色字体等。
为了简化处理,本次学习中只考虑蓝底白字的车牌。

2.1.1 图像加载与灰度化
import cv2img = cv2.imread('../data/bmw01.jpg')# 调整图片大小
img = cv2.resize(img, (1024, 800))# 灰度图
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)# 显示效果
cv2.imshow('gray', gray)
cv2.waitKey(0)
cv2.destroyAllWindows()
显示结果如下:

2.1.2 双边滤波去除噪声
# 双边滤波
blf = cv2.bilateralFilter(gray, 13, 15, 15)
show_image('bilateralFilter', blf)
显示结果如下:

2.1.3 边缘检测
# 边缘检测
edged = cv2.Canny(blf, 30, 200)
show_image('canny', edged)
显示结果如下:

2.1.4 寻找车牌轮廓(四边形)
cv2.findContours说明:
- opencv3.x
image, contours, hierarchy = cv.findContours(image, mode, method[, contours[, hierarchy[, offset]]])
- opencv2.x和4.x
contours, hierarchy = cv.findContours(image, mode, method[, contours[, hierarchy[, offset]]])
OpenCV中HSV空间颜色对照表

提取图像区域的颜色
def reg_area_color(image):"""找到原图像最多的颜色,当该颜色为红色或蓝色时返回该颜色的名称"""kernel = np.ones((35, 35), np.uint8)hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)# 以上为图像处理Open = cv2.morphologyEx(hsv, cv2.MORPH_OPEN, kernel)# 对Open图像的H通道进行直方图统计hist = cv2.calcHist([Open], [0], None, [180], [0, 180])# 找到直方图hist中列方向最大的点hist_maxhist_max = np.where(hist == np.max(hist))# hist_max[0]为hist_max的行方向的值,即H的值,H在0~10为红色if 0 < hist_max[0] < 10:res_color = 'red'elif 100 < hist_max[0] < 124: # H在100~124为蓝色res_color = 'blue'else:# H不在前两者之间跳出函数res_color = 'unknow'return res_color
寻找车牌轮廓:
# 寻找轮廓(图像矩阵,输出模式,近似方法)
contours, _ = cv2.findContours(edged.copy(), cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
# 根据区域大小排序取前十
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:10]
screenCnt = None
# 遍历轮廓,找到车牌轮廓
for c in contours:if cv2.contourArea(c) > 1024 * 768 * 0.05:continue# 计算轮廓周长(轮廓,是否闭合)peri = cv2.arcLength(c, True)# 折线化(轮廓,阈值(越小越接近曲线),是否闭合)返回折线顶点坐标approx = cv2.approxPolyDP(c, 0.018 * peri, True)# 获取四个顶点(即四边形, 左下/右下/右上/左上if len(approx) == 4:# [参数]左上角纵坐标:左下角纵坐标,左上角横坐标:右上角横坐标crop_image = img[approx[3][0][1]:approx[0][0][1], approx[3][0][0]:approx[2][0][0]]show_image('crop', crop_image)if 'blue' == reg_area_color(crop_image):screenCnt = approxbreak
# 如果找到了四边形
if screenCnt is not None:# 根据四个顶点坐标对img画线(图像矩阵,轮廓坐标集,轮廓索引,颜色,线条粗细)cv2.drawContours(img, [screenCnt], -1, (0, 0, 255), 3)show_image('contour', img)
运行结果显示:

2.1.5 图像位运算进行遮罩
"""遮罩"""
# 创建一个灰度图一样大小的图像矩阵
mask = np.zeros(gray.shape, np.uint8)
# 将创建的图像矩阵的车牌区域画成白色
cv2.drawContours(mask, [screenCnt], 0, 255, -1, )
# 图像位运算进行遮罩
mask_image = cv2.bitwise_and(img, img, mask=mask)
show_image('mask_image', mask_image)
运行结果显示:

2.1.6 图像剪裁
"""图像剪裁"""
# 获取车牌区域的所有坐标点
(x, y) = np.where(mask == 255)
# 获取底部顶点坐标
(topx, topy) = (np.min(x), np.min(y))
# 获取底部坐标
(bottomx, bottomy,) = (np.max(x), np.max(y))
# 剪裁
Cropped = gray[topx:bottomx, topy:bottomy]
运行结果显示:

2.1.7 OCR字符识别
paddleocr是一款轻量型字符识别工具库,支持多语言识别,支持pip安装与自定义训练。
- conda下工具类安装
pip install paddleocr -i https://mirror.baidu.com/pypi/simple
pip install paddlepaddle -i https://mirror.baidu.com/pypi/simple
代码实现:
"""OCR识别"""# 使用CPU预加载,不用GPU
ocr = PaddleOCR(use_angle_cls=True, use_gpu=False, ocr_version='PP-OCRv3')
text = ocr.ocr(cropped, cls=True)
for t in text:print(t[0][1])
运行结果显示如下:
[2023/11/15 20:57:43] ppocr DEBUG: dt_boxes num : 1, elapsed : 0.016942501068115234
[2023/11/15 20:57:43] ppocr DEBUG: cls num : 1, elapsed : 0.013955354690551758
[2023/11/15 20:57:43] ppocr DEBUG: rec_res num : 1, elapsed : 0.12021970748901367
('苏A·0MR20', 0.8559348583221436)
2.2 完整代码实现
import cv2
import numpy as np
from paddleocr import PaddleOCRdef show_image(desc, image):cv2.imshow(desc, image)cv2.waitKey(0)cv2.destroyAllWindows()def reg_area_color(image):"""找到原图像最多的颜色,当该颜色为红色或蓝色时返回该颜色的名称"""kernel = np.ones((35, 35), np.uint8)hsv = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)# 以上为图像处理Open = cv2.morphologyEx(hsv, cv2.MORPH_OPEN, kernel)# 对Open图像的H通道进行直方图统计hist = cv2.calcHist([Open], [0], None, [180], [0, 180])# 找到直方图hist中列方向最大的点hist_maxhist_max = np.where(hist == np.max(hist))# hist_max[0]为hist_max的行方向的值,即H的值,H在0~10为红色if 0 < hist_max[0] < 10:res_color = 'red'elif 100 < hist_max[0] < 124: # H在100~124为蓝色res_color = 'blue'else:# H不在前两者之间跳出函数res_color = 'unknow'return res_colorimg = cv2.imread('../data/bmw01.jpg')# 调整图片大小
img = cv2.resize(img, (1024, 768))# 灰度图
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
show_image('gray', gray)# 双边滤波
blf = cv2.bilateralFilter(gray, 13, 15, 15)
show_image('bilateralFilter', blf)# 边缘检测
edged = cv2.Canny(blf, 30, 200)
show_image('canny', edged)# 寻找轮廓(图像矩阵,输出模式,近似方法)
contours, _ = cv2.findContours(edged.copy(), cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
# 根据区域大小排序取前十
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:10]
screenCnt = None
# 遍历轮廓,找到车牌轮廓
for c in contours:if cv2.contourArea(c) > 1024 * 768 * 0.05:continue# 计算轮廓周长(轮廓,是否闭合)peri = cv2.arcLength(c, True)# 折线化(轮廓,阈值(越小越接近曲线),是否闭合)返回折线顶点坐标approx = cv2.approxPolyDP(c, 0.018 * peri, True)# 获取四个顶点(即四边形, 左下/右下/右上/左上if len(approx) == 4:# [参数]左上角纵坐标:左下角纵坐标,左上角横坐标:右上角横坐标crop_image = img[approx[3][0][1]:approx[0][0][1], approx[3][0][0]:approx[2][0][0]]show_image('crop', crop_image)if 'blue' == reg_area_color(crop_image):screenCnt = approxbreak
# 如果找到了四边形
if screenCnt is not None:# 根据四个顶点坐标对img画线(图像矩阵,轮廓坐标集,轮廓索引,颜色,线条粗细)cv2.drawContours(img, [screenCnt], -1, (0, 0, 255), 3)show_image('contour', img)"""遮罩"""
# 创建一个灰度图一样大小的图像矩阵
mask = np.zeros(gray.shape, np.uint8)
# 将创建的图像矩阵的车牌区域画成白色
cv2.drawContours(mask, [screenCnt], 0, 255, -1, )
# 图像位运算进行遮罩
mask_image = cv2.bitwise_and(img, img, mask=mask)
show_image('mask_image', mask_image)"""图像剪裁"""
# 获取车牌区域的所有坐标点
(x, y) = np.where(mask == 255)
# 获取底部顶点坐标
(topx, topy) = (np.min(x), np.min(y))
# 获取底部坐标
(bottomx, bottomy,) = (np.max(x), np.max(y))
# 剪裁
cropped = gray[topx:bottomx, topy:bottomy]
show_image('cropped', cropped)"""OCR识别"""
# 使用CPU预加载,不用GPU
ocr = PaddleOCR(use_angle_cls=True, use_gpu=False, ocr_version='PP-OCRv3')
text = ocr.ocr(cropped, cls=True)
for t in text:print(t[0][1])
相关文章:
计算机视觉:使用opencv实现车牌识别
1 引言 汽车车牌识别(License Plate Recognition)是一个日常生活中的普遍应用,特别是在智能交通系统中,汽车牌照识别发挥了巨大的作用。汽车牌照的自动识别技术是把处理图像的方法与计算机的软件技术相连接在一起,以准…...
用封面预测书的价格【图像回归】
今天,我将介绍计算机视觉的深度学习应用,用封面简单地估算一本书的价格。 我没有看到很多关于图像回归的文章,所以我为你们写这篇文章。 距离我上一篇文章已经过去很长时间了,我不得不承认,作为一名数据科学家&#x…...
阿里云服务器e实例40G ESSD Entry系统盘、2核2G3M带宽99元
阿里云99元服务器新老用户同享2核2G经济型e实例、3M固定带宽和40G ESSD Entry系统盘,老用户也可以买,续费不涨价依旧是99元一年,阿里云百科aliyunbaike.com分享阿里云3M带宽服务器40G ESSD Entry云盘性能说明: 阿里云99元服务器配…...
Datawhale智能汽车AI挑战赛
1.赛题解析 赛题地址:https://tianchi.aliyun.com/competition/entrance/532155 任务: 输入:元宇宙仿真平台生成的前视摄像头虚拟视频数据(8-10秒左右);输出:对视频中的信息进行综合理解&…...
pyclipper和ClipperLib操作多边型
目录 1. 等距离缩放多边形 1.1 python 1.2 c 1. 等距离缩放多边形 1.1 python 环境配置pip install opencv-python opencv-contrib-python pip install pyclipper pip install numpy import cv2 import numpy as np import pyclipperdef equidistant_zoom_contour(contour…...
Golang 协程、主线程
Go协程、Go主线程 1)Go主线程(有程序员直接称为线程/也可以理解成进程):一个Go线程上,可以起多个协程,你可以这样理解,协程是轻量级的线程。 2)Go协程的特点 有独立的栈空间 共享程序堆空间 调度由用户控制 协程是轻量级的线程 go线程-…...
【SA8295P 源码分析】125 - MAX96712 解串器 start_stream、stop_stream 寄存器配置 过程详细解析
【SA8295P 源码分析】125 - MAX96712 解串器 start_stream、stop_stream 寄存器配置 过程详细解析 一、sensor_detect_device():MAX96712 检测解串器芯片是否存在,获取chip_id、device_revision二、sensor_detect_device_channels() :MAX96712 解串器 寄存器初始化 及 detec…...
pandas教程:Apply:General split-apply-combine 通常的分割-应用-合并
文章目录 10.3 Apply:General split-apply-combine(应用:通用的分割-应用-合并)1 Suppressing the Group Keys(抑制组键)2 Quantile and Bucket Analysis(分位数与桶分析)3 Example:…...
第一讲之递归与递推下篇
第一讲之递归与递推下篇 带分数费解的开关飞行员兄弟翻硬币 带分数 用暴力将所有全排列的情况都算出来 > 有三个数,a,b,c 每种排列情况,可以用两层for循环,暴力分为三个部分,每个部分一个数 当然注意这里,第一层fo…...
第十六篇-Awesome ChatGPT Prompts-备份
Awesome ChatGPT Prompts——一个致力于提供挖掘ChatGPT能力的Prompt收集网站 https://prompts.chat/ 2023-11-16内容如下 ✂️Act as a Linux Terminal Contributed by: f Reference: https://www.engraved.blog/building-a-virtual-machine-inside/ I want you to act as a…...
Python Web框架Django
Python Web框架Django Django简介第一个Django应用Django核心概念Django django-adminDjango项目结构Django配置文件settingsDjango创建和配置应用Django数据库配置Django后台管理Django模型Django模型字段Django模型关联关系Django模型Meta 选项Django模型属性ManagerDjango模…...
1.Spring的简单使用
简介 本文是介绍spring源码的开始,先了解最基础的使用,最深入源码。 spring源码下载地址 https://github.com/spring-projects/spring-framework.git 依赖 依赖 spring-context dependencies {implementation(project(":spring-context")…...
02.智慧商城——vant组件库使用和vw适配
01. vant组件库及Vue周边的其他组件库 组件库:第三方封装好了很多很多的组件,整合到一起就是一个组件库。 https://vant-contrib.gitee.io/vant/v2/#/zh-CN/ 比如日历组件、键盘组件、打分组件、下拉筛选组件等 组件库并不是唯一的,常用的组…...
Android笔记(十三):结合JetPack Compose和CameraX实现视频的录制和存储
在“Android笔记(八):基于CameraX库结合Compose和传统视图组件PreviewView实现照相机画面预览和照相功能”,文中介绍了拍照功能的实现,在本文中将介绍结合JetPack Compose和CameraX实现视频的录制。 新建一个项目 在项…...
【开题报告】基于SpringBoot的音乐鉴赏平台的设计与实现
1.研究背景与意义 音乐是人类文化的重要组成部分,具有广泛的影响力和吸引力。然而,随着数字化时代的到来,传统的音乐鉴赏方式面临一些挑战。因此,设计和开发一个基于Spring Boot的音乐鉴赏平台,能够满足用户对音乐欣赏…...
云原生 黑马Kubernetes教程(K8S教程)笔记——第一章 kubernetes介绍——Master集群控制节点、Node工作负载节点、Pod控制单元
参考文章:kubernetes介绍 文章目录 第一章 kubernetes介绍1.1 应用部署方式演变传统部署:互联网早期,会直接将应用程序部署在物理机上虚拟化部署:可以在一台物理机上运行多个虚拟机,每个虚拟机都是独立的一个环境&…...
ElasticSearch 安装(单机版本)
文章目录 ElasticSearch 安装(单机版本)环境配置下载安装包调整系统参数安装启动并验证 ElasticSearch 安装(单机版本) 此文档演示 ElasticSearch 的单机版本在 CentOS 7 环境下的安装方式以及相关的配置。 环境配置 Linux 主机一…...
读书笔记:《BackTrader 量化交易案例图解》
BackTrader 量化软件:https://github.com/mementum/backtrader -> bt 量化框架(前身):https://github.com/pmorissette/bt-> ffn 量化框架(前前身):https://github.com/pmorissette/ffn T…...
CentOS 7 免密密钥登陆sftp服务 —— 筑梦之路
为什么用sftp而不是ftp? sftp是使用ssh协议安全加密的文件传输协议,ftp在很多时候都是使用的明文传输,相对来说容易被抓包,存在安全隐患。 需求说明 1. 使用sftp代替ftp来做文件存储,锁定目录,不允许用户切…...
记一次 .NET 某券商论坛系统 卡死分析
一:背景 1. 讲故事 前几个月有位朋友找到我,说他们的的web程序没有响应了,而且监控发现线程数特别高,内存也特别大,让我帮忙看一下怎么回事,现在回过头来几经波折,回味价值太浓了。 二&#…...
wordpress后台更新后 前端没变化的解决方法
使用siteground主机的wordpress网站,会出现更新了网站内容和修改了php模板文件、js文件、css文件、图片文件后,网站没有变化的情况。 不熟悉siteground主机的新手,遇到这个问题,就很抓狂,明明是哪都没操作错误&#x…...
IGP(Interior Gateway Protocol,内部网关协议)
IGP(Interior Gateway Protocol,内部网关协议) 是一种用于在一个自治系统(AS)内部传递路由信息的路由协议,主要用于在一个组织或机构的内部网络中决定数据包的最佳路径。与用于自治系统之间通信的 EGP&…...
java调用dll出现unsatisfiedLinkError以及JNA和JNI的区别
UnsatisfiedLinkError 在对接硬件设备中,我们会遇到使用 java 调用 dll文件 的情况,此时大概率出现UnsatisfiedLinkError链接错误,原因可能有如下几种 类名错误包名错误方法名参数错误使用 JNI 协议调用,结果 dll 未实现 JNI 协…...
vue3 字体颜色设置的多种方式
在Vue 3中设置字体颜色可以通过多种方式实现,这取决于你是想在组件内部直接设置,还是在CSS/SCSS/LESS等样式文件中定义。以下是几种常见的方法: 1. 内联样式 你可以直接在模板中使用style绑定来设置字体颜色。 <template><div :s…...
WordPress插件:AI多语言写作与智能配图、免费AI模型、SEO文章生成
厌倦手动写WordPress文章?AI自动生成,效率提升10倍! 支持多语言、自动配图、定时发布,让内容创作更轻松! AI内容生成 → 不想每天写文章?AI一键生成高质量内容!多语言支持 → 跨境电商必备&am…...
零基础设计模式——行为型模式 - 责任链模式
第四部分:行为型模式 - 责任链模式 (Chain of Responsibility Pattern) 欢迎来到行为型模式的学习!行为型模式关注对象之间的职责分配、算法封装和对象间的交互。我们将学习的第一个行为型模式是责任链模式。 核心思想:使多个对象都有机会处…...
Caliper 配置文件解析:config.yaml
Caliper 是一个区块链性能基准测试工具,用于评估不同区块链平台的性能。下面我将详细解释你提供的 fisco-bcos.json 文件结构,并说明它与 config.yaml 文件的关系。 fisco-bcos.json 文件解析 这个文件是针对 FISCO-BCOS 区块链网络的 Caliper 配置文件,主要包含以下几个部…...
Java面试专项一-准备篇
一、企业简历筛选规则 一般企业的简历筛选流程:首先由HR先筛选一部分简历后,在将简历给到对应的项目负责人后再进行下一步的操作。 HR如何筛选简历 例如:Boss直聘(招聘方平台) 直接按照条件进行筛选 例如:…...
【Post-process】【VBA】ETABS VBA FrameObj.GetNameList and write to EXCEL
ETABS API实战:导出框架元素数据到Excel 在结构工程师的日常工作中,经常需要从ETABS模型中提取框架元素信息进行后续分析。手动复制粘贴不仅耗时,还容易出错。今天我们来用简单的VBA代码实现自动化导出。 🎯 我们要实现什么? 一键点击,就能将ETABS中所有框架元素的基…...
二维FDTD算法仿真
二维FDTD算法仿真,并带完全匹配层,输入波形为高斯波、平面波 FDTD_二维/FDTD.zip , 6075 FDTD_二维/FDTD_31.m , 1029 FDTD_二维/FDTD_32.m , 2806 FDTD_二维/FDTD_33.m , 3782 FDTD_二维/FDTD_34.m , 4182 FDTD_二维/FDTD_35.m , 4793...
