基于Opencv的Python车牌识别实战【一键运行】
该项目基于Python和OpenCV实现车牌识别,含图像预处理、定位、分割及模板匹配等步骤。先通过灰度转换、噪声过滤等预处理图像,再经形态学操作定位车牌,分割字符后按位置排序,最后用模板匹配识别字符,可输出车牌号码,在智能交通等领域实用。

基于Opencv的Python车牌识别实战【一键运行】

一. 项目背景
一键运行
免费影视、动漫、音乐、游戏、小说资源长期稳定更新! 👉 点此立即查看 👈
该项目旨在通过Python编程语言结合OpenCV库,实现一个完整的车牌识别系统。项目将演示从图像预处理到车牌定位、分割,以及最终通过模板匹配技术实现车牌号码的自动识别。这一技术在智能交通、车辆管理和监控等领域具有显著的实际应用价值,能够显著提升交通管理的效率和准确性。

二. 项目亮点
OpenCV应用:本项目采用OpenCV这一强大的图像处理和计算机视觉库,实现高效的图像分析和处理功能。OpenCV的集成使得车牌识别过程更加精确和快速。
Python编程:选择Python作为开发语言,得益于其简洁的语法和丰富的库支持,使得开发过程更加高效。Python的易学性和广泛的社区资源为项目提供了强大的后盾。
立即学习“Python免费学习笔记(深入)”;
高级图像处理:项目中运用了多种高级图像处理技术,包括但不限于灰度转换以增强图像对比度、噪声过滤以净化图像质量、边缘检测以识别图像轮廓、形态学操作以改善图像结构,以及透视变换以校正图像视角。
创新算法集成:通过结合多种图像处理技术,项目开发了一套创新的算法流程,有效提升了车牌识别的准确性和鲁棒性,特别是在复杂环境下的表现。
实用性与灵活性:项目不仅注重技术实现,还强调算法的实用性和灵活性,确保能够适应不同的应用场景和需求,如智能交通监控、车辆自动登记等。

三. 技术原理
OpenCV(Open Source Computer Vision Library)是一个功能强大的开源计算机视觉库,广泛应用于图像处理和计算机视觉任务。它提供了丰富的算法和功能,包括但不限于图像处理、视频分析、物体识别、机器学习等 。
技术原理方面,OpenCV主要基于以下几个方面:
图像表示:图像在OpenCV中通常以矩阵的形式表示,其中每个元素对应图像的一个像素点,像素值通常以BGR格式存储 。图像处理技术:OpenCV提供了大量的图像处理技术,如灰度化、噪声去除、边缘检测、形态学操作、透视变换等 。特征提取:在图像处理的基础上,OpenCV能够进行特征提取,例如角点检测、斑点检测等,这些特征可以用于后续的图像分析 。目标检测与跟踪:OpenCV实现了多种目标检测算法,如Haar Cascade、HOG等,以及目标跟踪算法,如CamShift、MeanShift等 。深度学习集成:OpenCV的dnn模块支持多种深度学习框架,可以加载预训练模型进行图像分类、目标检测等任务 。OpenCV的架构主要由核心模块、高级模块、辅助模块以及接口和平台适配组成。核心模块提供图像处理和计算机视觉的基础功能,高级模块提供更复杂的视觉功能,辅助模块提供文件读写等辅助功能,接口和平台适配使得OpenCV可以跨语言和平台使用 。
在实际应用中,OpenCV可以用于人脸检测、物体识别、图像拼接、视频分析等多种场景。例如,使用Haar Cascade算法可以检测图像中的人脸位置,物体识别可以通过深度学习算法实现,图像拼接可以通过Stitcher类将多个图像拼接成一个大视场图像 。

四. 代码实现
4.1. 导入依赖
In [323]import cv2from matplotlib import pyplot as pltimport osimport numpy as npfrom PIL import ImageFont, ImageDraw, Image登录后复制
4.2. 图像预处理
cv2.GaussianBlur参数说明:
src:输入图像,可以是任意数量的通道,这些通道可以独立处理,但深度应为 CV_8U、CV_16U、CV_16S、CV_32F 或 CV_64F。ksize:高斯核的大小,必须是正奇数,例如 (3, 3)、(5, 5) 等。如果 ksize 的值为零,那么它会根据 sigmaX 和 sigmaY 的值来计算。sigmaX:X 方向上的高斯核标准偏差。dst:输出图像,大小和类型与 src 相同。sigmaY:Y 方向上的高斯核标准偏差,如果 sigmaY 是零,那么它会与 sigmaX 的值相同。如果 sigmaY 是负数,那么它会从 ksize.width 和 ksize.height 计算得出。borderType:像素外插法,有默认值。In [324]def plt_show0(img): b,g,r = cv2.split(img) img = cv2.merge([r, g, b]) plt.imshow(img) plt.show()def plt_show(img): plt.imshow(img,cmap='gray') plt.show()def gray_guss(image): image = cv2.GaussianBlur(image, (3, 3), 0) gray_image = cv2.cvtColor(image, cv2.COLOR_RGB2GRAY) return gray_image登录后复制
运行下面的cell,显示处理的原始图片
In [325]from IPython.display import Image# 显示图片Image(filename='work/1.webp')登录后复制
登录后复制In [326]
origin_image = cv2.imread('work/1.webp')# 高斯去噪image = origin_image.copy()gray_image = gray_guss(image)Sobel_x = cv2.Sobel(gray_image, cv2.CV_16S, 1, 0)absX = cv2.convertScaleAbs(Sobel_x)image = absX# 图像阈值化操作——获得二值化图ret, image = cv2.threshold(image, 0, 255, cv2.THRESH_OTSU)# 显示灰度图像plt_show(image)登录后复制登录后复制登录后复制登录后复制登录后复制登录后复制登录后复制登录后复制
4.3. 车牌定位
In [327]kernelX = cv2.getStructuringElement(cv2.MORPH_RECT, (30, 10))image = cv2.morphologyEx(image, cv2.MORPH_CLOSE, kernelX,iterations = 1)# 显示灰度图像plt_show(image)登录后复制
登录后复制登录后复制登录后复制登录后复制登录后复制登录后复制登录后复制In [328]
# 腐蚀(erode)和膨胀(dilate)kernelX = cv2.getStructuringElement(cv2.MORPH_RECT, (50, 1))kernelY = cv2.getStructuringElement(cv2.MORPH_RECT, (1, 20))#x方向进行闭操作(抑制暗细节)image = cv2.dilate(image, kernelX)image = cv2.erode(image, kernelX)#y方向的开操作image = cv2.erode(image, kernelY)image = cv2.dilate(image, kernelY)# 中值滤波(去噪)image = cv2.medianBlur(image, 21)# 显示灰度图像plt_show(image)登录后复制
登录后复制登录后复制登录后复制登录后复制登录后复制登录后复制登录后复制In [329]
contours, hierarchy = cv2.findContours(image, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)for item in contours: rect = cv2.boundingRect(item) x = rect[0] y = rect[1] weight = rect[2] height = rect[3] # 根据轮廓的形状特点,确定车牌的轮廓位置并截取图像 if (weight > (height * 3)) and (weight < (height * 4.5)): image = origin_image[y:y + height, x:x + weight] plt_show(image)登录后复制
登录后复制登录后复制登录后复制登录后复制登录后复制登录后复制登录后复制
运行下面的cell,对车牌字符分割
In [330]# 图像去噪灰度处理gray_image = gray_guss(image)ret, image = cv2.threshold(gray_image, 0, 255, cv2.THRESH_OTSU) # 阈值化plt_show(image)登录后复制
登录后复制登录后复制登录后复制登录后复制登录后复制登录后复制登录后复制In [331]
#膨胀操作kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (4, 4))image = cv2.dilate(image, kernel)plt_show(image)登录后复制
登录后复制登录后复制登录后复制登录后复制登录后复制登录后复制登录后复制
运行下面的cell,对车牌号排序
In [332]# 查找轮廓contours, hierarchy = cv2.findContours(image, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)words = []word_images = []#对所有轮廓逐一操作for item in contours: word = [] rect = cv2.boundingRect(item) x = rect[0] y = rect[1] weight = rect[2] height = rect[3] word.append(x) word.append(y) word.append(weight) word.append(height) words.append(word)words = sorted(words,key=lambda s:s[0],reverse=False)i = 0#word中存放轮廓的起始点和宽高for word in words: # 筛选字符的轮廓 if (word[3] > (word[2] * 1.5)) and (word[3] < (word[2] * 5.5)) and (word[2] > 10): i = i+1 if word[2] < 15: splite_image = image[word[1]:word[1] + word[3], word[0]-word[2]:word[0] + word[2]*2] else: splite_image = image[word[1]:word[1] + word[3], word[0]:word[0] + word[2]] word_images.append(splite_image)登录后复制In [333]
for i,j in enumerate(word_images): plt.subplot(1,7,i+1) plt.imshow(word_images[i],cmap='gray')plt.show()登录后复制
登录后复制
4.4. 模版匹配
解压模版文件,文件路径在/home/aistudio/work/Template.zip,运行完之后可以注释下面的cell
In [334]%%capture!unzip /home/aistudio/work/Template.zip -d /home/aistudio/work登录后复制In [335]
# 准备模板(template[0-9]为数字模板;)template = ['0','1','2','3','4','5','6','7','8','9', 'A','B','C','D','E','F','G','H','J','K','L','M','N','P','Q','R','S','T','U','V','W','X','Y','Z', '藏','川','鄂','甘','赣','贵','桂','黑','沪','吉','冀','津','晋','京','辽','鲁','蒙','闽','宁', '青','琼','陕','苏','皖','湘','新','渝','豫','粤','云','浙']# 读取一个文件夹下的所有图片,输入参数是文件名,返回模板文件地址列表def read_directory(directory_name): referImg_list = [] for filename in os.listdir(directory_name): referImg_list.append(directory_name + "/" + filename) return referImg_list# 获得中文模板列表(只匹配车牌的第一个字符)def get_chinese_words_list(): chinese_words_list = [] for i in range(34,64): #将模板存放在字典中 c_word = read_directory('/home/aistudio/work/Template/'+ template[i]) chinese_words_list.append(c_word) return chinese_words_listchinese_words_list = get_chinese_words_list()# 获得英文模板列表(只匹配车牌的第二个字符)def get_eng_words_list(): eng_words_list = [] for i in range(10,34): e_word = read_directory('/home/aistudio/work/Template/'+ template[i]) eng_words_list.append(e_word) return eng_words_listeng_words_list = get_eng_words_list()# 获得英文和数字模板列表(匹配车牌后面的字符)def get_eng_num_words_list(): eng_num_words_list = [] for i in range(0,34): word = read_directory('/home/aistudio/work/Template/'+ template[i]) eng_num_words_list.append(word) return eng_num_words_listeng_num_words_list = get_eng_num_words_list()登录后复制In [336]# 获得英文和数字模板列表(匹配车牌后面的字符)def get_eng_num_words_list(): eng_num_words_list = [] for i in range(0,34): word = read_directory('/home/aistudio/work/Template/'+ template[i]) eng_num_words_list.append(word) return eng_num_words_listeng_num_words_list = get_eng_num_words_list()# 读取一个模板地址与图片进行匹配,返回得分def template_score(template,image): #将模板进行格式转换 template_img=cv2.imdecode(np.fromfile(template,dtype=np.uint8),1) template_img = cv2.cvtColor(template_img, cv2.COLOR_RGB2GRAY) #模板图像阈值化处理——获得黑白图 ret, template_img = cv2.threshold(template_img, 0, 255, cv2.THRESH_OTSU)# height, width = template_img.shape# image_ = image.copy()# image_ = cv2.resize(image_, (width, height)) image_ = image.copy() #获得待检测图片的尺寸 height, width = image_.shape # 将模板resize至与图像一样大小 template_img = cv2.resize(template_img, (width, height)) # 模板匹配,返回匹配得分 result = cv2.matchTemplate(image_, template_img, cv2.TM_CCOEFF) return result[0][0]# 对分割得到的字符逐一匹配def template_matching(word_images): results = [] for index,word_image in enumerate(word_images): if index==0: best_score = [] for chinese_words in chinese_words_list: score = [] for chinese_word in chinese_words: result = template_score(chinese_word,word_image) score.append(result) best_score.append(max(score)) i = best_score.index(max(best_score)) # print(template[34+i]) r = template[34+i] results.append(r) continue if index==1: best_score = [] for eng_word_list in eng_words_list: score = [] for eng_word in eng_word_list: result = template_score(eng_word,word_image) score.append(result) best_score.append(max(score)) i = best_score.index(max(best_score)) # print(template[10+i]) r = template[10+i] results.append(r) continue else: best_score = [] for eng_num_word_list in eng_num_words_list: score = [] for eng_num_word in eng_num_word_list: result = template_score(eng_num_word,word_image) score.append(result) best_score.append(max(score)) i = best_score.index(max(best_score)) # print(template[i]) r = template[i] results.append(r) continue return resultsword_images_ = word_images.copy()# 调用函数获得结果result = template_matching(word_images_)print(result)print( "".join(result))登录后复制['渝', 'B', 'F', 'U', '8', '7', '1']渝BFU871登录后复制登录后复制
4.5. 结果展示
In [337]import cv2from matplotlib import pyplot as pltimport osimport numpy as npfrom PIL import ImageFont, ImageDraw, Imageheight,weight = origin_image.shape[0:2]image_1 = origin_image.copy()cv2.rectangle(image_1, (int(0.2*weight), int(0.75*height)), (int(weight*0.9), int(height*0.95)), (0, 255, 0), 5)#设置需要显示的字体fontpath = "/home/aistudio/work/simsun.ttc"font = ImageFont.truetype(fontpath,64)img_pil = Image.fromarray(image_1)draw = ImageDraw.Draw(img_pil)#绘制文字信息draw.text((int(0.2*weight)+25, int(0.75*height)), "".join(result), font = font, fill = (255, 255, 0))bk_img = np.array(img_pil)print(result)print( "".join(result))plt_show0(bk_img)登录后复制
['渝', 'B', 'F', 'U', '8', '7', '1']渝BFU871登录后复制登录后复制
登录后复制登录后复制登录后复制登录后复制登录后复制登录后复制登录后复制
相关攻略
Pywinrm 通过Windows远程管理(WinRM)协议,让Python能够像操作本地一样执行远程Windows命令,真正打通了跨平台管理的最后一公里。 在混合IT环境中,Linux机器管理Wi
早些时候,聊过 Python 领域那场惊心动魄的供应链攻击。当时我就感叹,虽然我们 JavaScript 开发者对这类套路烂熟于心,但亲眼目睹这种规模的“投毒”还是头一次。 早些时候,聊过 Pyth
Toga 是 BeeWare 家族的核心成员,号称“写一次,跑遍所有平台”,而且用的是系统原生控件,不是那种一看就是网页套壳的界面 。 写了这么多年 Python,你是不是也想过:要是能一套代码跑
异常处理的核心:让错误在正确的地方被有效处理。正确的地方,就是别在底层就把异常吞了,也别在顶层还抛裸奔的 Exception。 异常处理写得好,半夜不用起来改 bug。1 你是不是也这么干过?tr
1 Skills机制概述 提起OpenClaw的Skills机制,不少人可能会把它想象成传统意义上的可执行插件。其实,它的内涵要更精妙一些。 简单说,Skills本质上是一套基于提示驱动的能力扩展机制。它并不是一个可以独立“跑”起来的程序模块,而是通过一份结构化描述文件(核心就是那个SKILL m
热门专题
热门推荐
加密货币行业翘首以盼的监管里程碑,终于有了实质性进展。美国证券交易委员会(SEC)主席保罗·阿特金斯(Paul Atkins)近日证实,那份允许加密项目在早期获得注册豁免权的“安全港”框架提案,已经正式送抵白宫,进入了最终审查阶段。 在范德堡大学与区块链协会联合举办的数字资产峰会上,阿特金斯透露了这
微策略Strategy报告:第一季录得144 6亿美元浮亏 再斥资约3 3亿美元买进4871枚比特币 市场震荡的威力有多大?看看Strategy的最新季报就明白了。根据其最新向美国证管会(SEC)提交的8-K报告,受市场剧烈波动影响,这家公司所持的比特币在第一季度录得了一笔惊人的数字——144 6亿
稳定币巨头Tether的动向,向来是加密世界的风向标。这不,它向Web3基础设施的版图扩张,又迈出了关键一步。公司执行长Paolo Ardoino在社交平台X上透露,其工程团队正在全力“烹制”一个新项目——去中心化搜索引擎 “Hypersearch”。这个消息一出,立刻引发了行业的广泛猜想。 采用D
基地位于Coinbase旗下以太坊Layer2网络Base的Seamless Protocol,日前正式宣告了服务的终结。这个曾经吸引了超过20万用户的原生DeFi借贷协议,在运营不到三年后,终究没能跑赢时间。它主打的核心产品是Integrated Leverage Markets(ILMs)——一
PAAL代币揭秘:深度解析Web3社区治理的核心钥匙 在去中心化自治组织的浪潮中,谁真正掌握了项目的话语权?PAAL代币提供了一套系统化的答案。它不仅是生态内流转的价值媒介,更是开启链上治理大门的核心凭证。通过持有并质押PAAL代币,用户能够对协议升级、资金分配乃至战略方向等关键事务投出决定性的一票





