车牌识别包括车牌检测(通过图像分割、特征提取获得车牌位置)+车牌识别(对检测到的车牌进行字符内容识别)。
一、基本流程如下:
1.车牌检测
1)读取需要进行车牌识别的图片;
2)对图像进行灰度化处理(高斯模糊可选择是否进行)和灰度拉伸;
3)进行开运算,消除图像中的噪声;
4)将灰度拉伸后的图像和开运算后的图像求差,并输出其绝对值;
5)将图像二值化,并利用Canny边缘算法提取图像中边缘轮廓;
6)进行闭运算操作,获得小连通域;
7)进行两次开运算操作,获得大连通域;
8)利用车牌长宽比筛选可能属于车牌区域的框,在原图中绘制矩形 。
2.车牌字符识别
1)对车牌ROI图像进行灰度化处理;
2)利用形态学运算中的闭运算消除灰度图像噪声点;
3)利用百度飞桨OCR识别车牌字符与位置;
4)将结果打印并在图片上显示出来。
二、实际代码测试:
1.输入图像:

2.输出图像:

三、注意事项
1.目前代码进行过单个车牌检测,未对多个车牌进行检测;
2.paddleOCR下载和配置,且容易出错,实际使用中速度较慢,可考虑使用EASYOCR作为代替。
附上代码
import cv2
from matplotlib import pyplot as plt
import os
import numpy as np
from paddleocr import PaddleOCR, draw_ocr
from PIL import Image, ImageDraw, ImageFont
#利用paddelOCR进行文字扫描,并输出结果
def text_scan(img_path):
ocr = PaddleOCR(use_angle_cls=True, use_gpu=False)
#img_path = r'test image/license_plate1.jpg'
result = ocr.ocr(img_path, cls=True)
for line in result:
#print(line)
return result
#在图片中写入将车牌信息
def infor_write(img,rect,result):
text=result[1][0]
cv2img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) # cv2和PIL中颜色的hex码的储存顺序不同
pilimg = Image.fromarray(cv2img)
#PIL图片上打印汉字
draw = ImageDraw.Draw(pilimg) # 图片上打印
font = ImageFont.truetype("simhei.ttf",20, encoding="utf-8") # 参数1:字体文件路径,参数2:字体大小
draw.text((rect[2], rect[1]), str(text), (0,255,0), font=font) # 参数1:打印坐标,参数2:文本,参数3:字体颜色,参数4:字体
#PIL图片转cv2 图片
cv2charimg = cv2.cvtColor(np.array(pilimg), cv2.COLOR_RGB2BGR)
return cv2charimg
#图像去噪灰度处理
def gray_guss(img):
img=cv2.GaussianBlur(img,(1,1),0)
gray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
return gray
#图像尺寸变换
def img_resize(img):
a=400*img.shape[0]/img.shape[1]
a=int(a)
img=cv2.resize(img,(400,a))
return img
#Sobel检测,x方向上的边缘检测(增强边缘信息)
def Sobel_detec(img):
Sobel_x = cv2.Sobel(img, cv2.CV_16S, 1, 0)
absX = cv2.convertScaleAbs(Sobel_x)
return absX
#寻找某区域最大外接矩形框4点坐标
def find_retangle(contour):
y,x=[],[]
for p in contour:
y.append(p[0][0])
x.append(p[0][1])
return [min(y),min(x),max(y),max(x)]
#寻找并定位车牌轮廓位置
def locate_license(img):
blocks=[]
contours,hierarchy=
cv2.findContours(img,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
for c in contours:
x,y,w,h=cv2.boundingRect(c)
r=find_retangle(c)
a=(r[2]-r[0])*(r[3]-r[1])#r=[min(y),min(x),max(y),max(x)]
s=(r[2]-r[0])/(r[3]-r[1])
#根据轮廓形状特点,确定车牌的轮廓位置并截取图像
if (w> (h * 3)) and (w < (h * 5)):
# img=oriimg[y:y+h,x:x+w]
# cv2.rectangle(oriimg, (x, y), (x+w, y+h), (0, 255, 0), 2)
blocks.append([r, a, s])
# 选出面积最大的3个区域
blocks = sorted(blocks, key=lambda b: b[1])[-3:] # 按照blocks第3个元素大小进行排序
# 使用颜色识别判断出最像车牌的区域
maxweight, maxindex = 0, -1
# 划分ROI区域
for i in range(len(blocks)):
b = oriimg[blocks[i][0][1]:blocks[i][0][3], blocks[i][0][0]:blocks[i][0][2]]
# RGB转HSV
hsv = cv2.cvtColor(b, cv2.COLOR_BGR2HSV)
# 蓝色车牌范围
lower = np.array([100, 50, 50])
upper = np.array([140, 255, 255])
# 根据阈值构建掩模
mask = cv2.inRange(hsv, lower, upper)
# 统计权值
w1 = 0
for m in mask:
w1 += m / 255
w2 = 0
for w in w1:
w2 += w
# 选出最大权值的区域
if w2 > maxweight:
maxindex = i
maxweight = w2
# print(blocks[maxindex][0])
return blocks[maxindex][0]#blocks[maxindex][0]即为车牌轮廓位置理想外轮廓
#图像预处理+车牌轮廓位置检测
def fine_lisecenpts(img):
# 图像去噪灰度处理
guss = gray_guss(img)
# Sobel检测,增强边缘信息
sobel = Sobel_detec(guss)
# 图像阈值化操作——获得二值化图
ret, threshold = cv2.threshold(sobel, 0, 255, cv2.THRESH_OTSU)
# # 对二值化图像进行边缘检测(可选,通过边缘检测后,最终进行形态学运算得到的轮廓面积更大)
# threshold=cv2.Canny(threshold,threshold.shape[0],threshold.shape[1])
#形态学运算(从图像中提取对表达和描绘区域形状有意义的图像分量)——闭操作
kernelX = cv2.getStructuringElement(cv2.MORPH_RECT, (30, 10))
closing = cv2.morphologyEx(threshold, cv2.MORPH_CLOSE, kernelX, iterations=1)
# 腐蚀(erode)和膨胀(dilate)
kernelX=cv2.getStructuringElement(cv2.MORPH_RECT,(50,1))
kernelY=cv2.getStructuringElement(cv2.MORPH_RECT,(1,20))
#x方向上进行闭操作(抑制暗细节)
img=cv2.dilate(closing,kernelX)
img=cv2.erode(img,kernelX)
#y方向上进行开操作
img=cv2.erode(img,kernelY)
img=cv2.dilate(img,kernelY)
#进行中值滤波去噪
Blur=cv2.medianBlur(img,15)
#寻找轮廓
rect=locate_license(Blur)
return rect,Blur
#车牌字符识别
def seg_char(rect_list,img):
img=oriimg[rect_list[1]:rect_list[3], rect_list[0]:rect_list[2]]
# 图像去噪灰度处理
gray=gray_guss(img)
# 图像阈值化操作-获得二值化图(可选)
#ret,charimage=cv2.threshold(gray,0,255,cv2.THRESH_BINARY_INV+cv2.THRESH_OTSU)
#图像进行闭运算
k1 = np.ones((1, 1), np.uint8)
close = cv2.morphologyEx(gray, cv2.MORPH_CLOSE, k1)
cv2.imshow('close', close)
cv2.imwrite('test image/Char_img.jpg',close)
cv2.waitKey()
res=text_scan(r'test image/Char_img.jpg')
return res
#主函数区
if __name__ == '__main__':
img=cv2.imread('test image/license_plate1.jpg')
# 改变图像尺寸
img=img_resize(img)
oriimg=img.copy()
#寻找到车牌外轮廓矩形坐标
rect, img=fine_lisecenpts(img)
#利用车牌轮廓坐标划分ROI区域用于字符识别,利用OCR识别车牌字符并返回字符串内容
result=seg_char(rect,oriimg)
#循环读取车牌字符串并写入到图片中
for list in result:
oriimg=infor_write(oriimg, rect, list)
cv2.rectangle(oriimg, (rect[0], rect[1]), (rect[2], rect[3]), (0, 255, 0), 2)
cv2.imshow('oriimg',oriimg)
cv2.waitKey()
关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。
这个问题在这里已经有了答案:关闭10年前。PossibleDuplicate:Pythonconditionalassignmentoperator对于这样一个简单的问题表示歉意,但是谷歌搜索||=并不是很有帮助;)Python中是否有与Ruby和Perl中的||=语句等效的语句?例如:foo="hey"foo||="what"#assignfooifit'sundefined#fooisstill"hey"bar||="yeah"#baris"yeah"另外,类似这样的东西的通用术语是什么?条件分配是我的第一个猜测,但Wikipediapage跟我想的不太一样。
什么是ruby的rack或python的Java的wsgi?还有一个路由库。 最佳答案 来自Python标准PEP333:Bycontrast,althoughJavahasjustasmanywebapplicationframeworksavailable,Java's"servlet"APImakesitpossibleforapplicationswrittenwithanyJavawebapplicationframeworktoruninanywebserverthatsupportstheservletAPI.ht
导读语言模型给我们的生产生活带来了极大便利,但同时不少人也利用他们从事作弊工作。如何规避这些难辨真伪的文字所产生的负面影响也成为一大难题。在3月9日智源Live第33期活动「DetectGPT:判断文本是否为机器生成的工具」中,主讲人Eric为我们讲解了DetectGPT工作背后的思路——一种基于概率曲率检测的用于检测模型生成文本的工具,它可以帮助我们更好地分辨文章的来源和可信度,对保护信息真实、防止欺诈等方面具有重要意义。本次报告主要围绕其功能,实现和效果等展开。(文末点击“阅读原文”,查看活动回放。)Ericmitchell斯坦福大学计算机系四年级博士生,由ChelseaFinn和Chri
导读:随着叮咚买菜业务的发展,不同的业务场景对数据分析提出了不同的需求,他们希望引入一款实时OLAP数据库,构建一个灵活的多维实时查询和分析的平台,统一数据的接入和查询方案,解决各业务线对数据高效实时查询和精细化运营的需求。经过调研选型,最终引入ApacheDoris作为最终的OLAP分析引擎,Doris作为核心的OLAP引擎支持复杂地分析操作、提供多维的数据视图,在叮咚买菜数十个业务场景中广泛应用。作者|叮咚买菜资深数据工程师韩青叮咚买菜创立于2017年5月,是一家专注美好食物的创业公司。叮咚买菜专注吃的事业,为满足更多人“想吃什么”而努力,通过美好食材的供应、美好滋味的开发以及美食品牌的孵
华为OD机试题本篇题目:明明的随机数题目输入描述输出描述:示例1输入输出说明代码编写思路最近更新的博客华为od2023|什么是华为od,od薪资待遇,od机试题清单华为OD机试真题大全,用Python解华为机试题|机试宝典【华为OD机试】全流程解析+经验分享,题型分享,防作弊指南华为o
之前在培训新生的时候,windows环境下配置opencv环境一直教的都是网上主流的vsstudio配置属性表,但是这个似乎对新生来说难度略高(虽然个人觉得完全是他们自己的问题),加之暑假之后对cmake实在是爱不释手,且这样配置确实十分简单(其实都不需要配置),故斗胆妄言vscode下配置CV之法。其实极为简单,图比较多所以很长。如果你看此文还配不好,你应该思考一下是不是自己的问题。闲话少说,直接开始。0.CMkae简介有的人到大二了都不知道cmake是什么,我不说是谁。CMake是一个开源免费并且跨平台的构建工具,可以用简单的语句来描述所有平台的编译过程。它能够根据当前所在平台输出对应的m
之前说过10之后的版本没有3dScan了,所以还是9.8的版本或者之前更早的版本。 3d物体扫描需要先下载扫描的APK进行扫面。首先要在手机上装一个扫描程序,扫描现实中的三维物体,然后上传高通官网,在下载成UnityPackage类型让Unity能够使用这个扫描程序可以从高通官网上进行下载,是一个安卓程序。点到Tools往下滑,找到VuforiaObjectScanner下载后解压数据线连接手机,将apk文件拷入手机安装然后刚才解压文件中的Media文件夹打开,两个PDF图打印第一张A4-ObjectScanningTarget.pdf,主要是用来辅助扫描的。好了,接下来就是扫描三维物体。将瓶
我想解析一个已经存在的.mid文件,改变它的乐器,例如从“acousticgrandpiano”到“violin”,然后将它保存回去或作为另一个.mid文件。根据我在文档中看到的内容,该乐器通过program_change或patch_change指令进行了更改,但我找不到任何在已经存在的MIDI文件中执行此操作的库.他们似乎都只支持从头开始创建的MIDI文件。 最佳答案 MIDIpackage会为您完成此操作,但具体方法取决于midi文件的原始内容。一个MIDI文件由一个或多个音轨组成,每个音轨是十六个channel中任何一个上的
C#实现简易绘图工具一.引言实验目的:通过制作窗体应用程序(C#画图软件),熟悉基本的窗体设计过程以及控件设计,事件处理等,熟悉使用C#的winform窗体进行绘图的基本步骤,对于面向对象编程有更加深刻的体会.Tutorial任务设计一个具有基本功能的画图软件**·包括简单的新建文件,保存,重新绘图等功能**·实现一些基本图形的绘制,包括铅笔和基本形状等,学习橡皮工具的创建**·设计一个合理舒适的UI界面**注明:你可能需要先了解一些关于winform窗体应用程序绘图的基本知识,以及关于GDI+类和结构的知识二.实验环境Windows系统下的visualstudio2017C#窗体应用程序三.