点击上方“小白学视觉”,选择加"星标"或“置顶”python
重磅干货,第一时间送达git
车牌识别的相关步骤github
1.车牌检测:第一步是从汽车上检测车牌所在位置。咱们将使用OpenCV中矩形的轮廓检测来寻找车牌。若是咱们知道车牌的确切尺寸,颜色和大体位置,则能够提升准确性。一般,也会将根据摄像机的位置和该特定国家/地区所使用的车牌类型来训练检测算法。可是图像可能并无汽车的存在,在这种状况下咱们将先进行汽车的,而后是车牌。算法
2.字符分割:检测到车牌后,咱们必须将其裁剪并保存为新图像。一样,这可使用OpenCV来完成。swift
3. 字符识别:如今,咱们在上一步中得到的新图像确定能够写上一些字符(数字/字母)。所以,咱们能够对其执行OCR(光学字符识别)以检测数字。安全
1.车牌检测bash
让咱们以汽车的样本图像为例,首先检测该汽车上的车牌。而后,咱们还将使用相同的图像进行字符分割和字符识别。若是您想直接进入代码而无需解释,则能够向下滚动至此页面的底部,提供完整的代码,或访问如下连接。https://github.com/GeekyPRAVEE/OpenCV-Projects/blob/master/LicensePlateRecoginition.ipynb 微信
在次使用的测试图像以下所示。app
图片来源连接:https : //rb.gy/lxmiuv 框架
第1步: 将图像调整为所需大小,而后将其灰度。相同的代码以下
img = cv2.resize(img, (620,480) )gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) #convert to grey scale
调整大小后,能够避免使用较大分辨率的图像而出现的如下问题,可是咱们要确保在调整大小后,车号牌仍保留在框架中。在处理图像时若是再也不须要处理颜色细节,那么灰度变化就必不可少,这加快了其余后续处理的速度。完成此步骤后,图像将像这样被转换
步骤2:每张图片都会包含有用和无用的信息,在这种状况下,对于咱们来讲,只有牌照是有用的信息,其他的对于咱们的程序几乎是无用的。这种无用的信息称为噪声。一般,使用双边滤波(模糊)会从图像中删除不须要的细节。
gray = cv2.bilateralFilter(gray, 13, 15, 15)
语法为 destination_image = cv2.bilateralFilter(source_image, diameter of pixel, sigmaColor, sigmaSpace)。咱们也能够将sigma颜色和sigma空间从15增长到更高的值,以模糊掉更多的背景信息,但请注意不要使有用的部分模糊。输出图像以下所示能够看到该图像中的背景细节(树木和建筑物)模糊了。这样,咱们能够避免程序处理这些区域。
步骤3:下一步是咱们执行边缘检测的有趣步骤。有不少方法能够作到,最简单和流行的方法是使用OpenCV中的canny edge方法。执行相同操做的行以下所示
edged = cv2.Canny(gray, 30, 200) #Perform Edge detection
语法为destination_image = cv2.Canny(source_image,thresholdValue 1,thresholdValue 2)。阈值谷1和阈值2是最小和最大阈值。仅显示强度梯度大于最小阈值且小于最大阈值的边缘。结果图像以下所示
步骤4:如今咱们能够开始在图像上寻找轮廓
contours=cv2.findContours(edged.copy(),cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)contours = imutils.grab_contours(contours)contours = sorted(contours,key=cv2.contourArea, reverse = True)[:10]screenCnt = None
一旦检测到计数器,咱们就将它们从大到小进行排序,并只考虑前10个结果而忽略其余结果。在咱们的图像中,计数器能够是具备闭合表面的任何事物,可是在全部得到的结果中,牌照号码也将存在,由于它也是闭合表面。
为了过滤得到的结果中的车牌图像,咱们将遍历全部结果,并检查其具备四个侧面和闭合图形的矩形轮廓。因为车牌确定是四边形的矩形。
for c in cnts: # approximate the contour peri = cv2.arcLength(c, True) approx = cv2.approxPolyDP(c, 0.018 * peri, True) # if our approximated contour has four points, then # we can assume that we have found our screen if len(approx) == 4: screenCnt = approx break
找到正确的计数器后,咱们将其保存在名为screenCnt的变量中,而后在其周围绘制一个矩形框,以确保咱们已正确检测到车牌。
步骤5:如今咱们知道车牌在哪里,剩下的信息对咱们来讲几乎没有用。所以,咱们能够对整个图片进行遮罩,除了车牌所在的地方。相同的代码以下所示
# Masking the part other than the number platemask = np.zeros(gray.shape,np.uint8)new_image = cv2.drawContours(mask,[screenCnt],0,255,-1,)new_image = cv2.bitwise_and(img,img,mask=mask)
被遮罩的新图像将以下所示
2.字符分割
车牌识别的下一步是经过裁剪车牌并将其保存为新图像,将车牌从图像中分割出来。而后,咱们可使用此图像来检测其中的字符。下面显示了从主图像裁剪出ROI(感兴趣区域)图像的代码
# Now crop(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+1, topy:bottomy+1]
结果图像以下所示。一般添加到裁剪图像中,若是须要,咱们还能够对其进行灰色处理和边缘化。这样作是为了改善下一步的字符识别。可是我发现即便使用原始图像也能够正常工做。
3.字符识别
该车牌识别的最后一步是从分割的图像中实际读取车牌信息。就像前面的教程同样,咱们将使用pytesseract包从图像读取字符。相同的代码以下
#Read the number platetext = pytesseract.image_to_string(Cropped, config='--psm 11')print("Detected license plate Number is:",text)
原始图像上印有数字“ CZ20FSE”,而且咱们的程序检测到它在jupyter笔记本上打印了相同的值。
车牌识别失败案例
车牌识别的完整代码,其中包含程序和咱们用来检查程序的测试图像。要记住,此方法的结果将不许确。准确度取决于图像的清晰度,方向,曝光等。为了得到更好的结果,您能够尝试同时实现机器学习算法。
这个案例中咱们的程序可以正确检测车牌并进行裁剪。可是,Tesseract库没法正确识别字符。OCR已将其识别为“ MH13CD 0036”,而不是实际的“ MH 13 CD 0096”。经过使用更好的方向图像或配置Tesseract引擎,能够纠正此类问题。
其余成功的例子
大多数时候,图像质量和方向都是正确的,程序可以识别车牌并从中读取编号。下面的快照显示了得到的成功结果。
完整代码
#@programming_feverimport cv2import imutilsimport numpy as npimport pytesseractpytesseract.pytesseract.tesseract_cmd = r'C:\Program Files (x86)\Tesseract-OCR\tesseract.exe'
img = cv2.imread('D://skoda1.jpg',cv2.IMREAD_COLOR)img = cv2.resize(img, (600,400) )
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) gray = cv2.bilateralFilter(gray, 13, 15, 15)
edged = cv2.Canny(gray, 30, 200) contours = cv2.findContours(edged.copy(), cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)contours = imutils.grab_contours(contours)contours = sorted(contours, key = cv2.contourArea, reverse = True)[:10]screenCnt = None
for c in contours: peri = cv2.arcLength(c, True) approx = cv2.approxPolyDP(c, 0.018 * peri, True) if len(approx) == 4: screenCnt = approx break
if screenCnt is None: detected = 0 print ("No contour detected")else: detected = 1
if detected == 1: cv2.drawContours(img, [screenCnt], -1, (0, 0, 255), 3)
mask = np.zeros(gray.shape,np.uint8)new_image = cv2.drawContours(mask,[screenCnt],0,255,-1,)new_image = cv2.bitwise_and(img,img,mask=mask)
(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+1, topy:bottomy+1]
text = pytesseract.image_to_string(Cropped, config='--psm 11')print("programming_fever's License Plate Recognition\n")print("Detected license plate Number is:",text)img = cv2.resize(img,(500,300))Cropped = cv2.resize(Cropped,(400,200))cv2.imshow('car',img)cv2.imshow('Cropped',Cropped)
cv2.waitKey(0)cv2.destroyAllWindows()
Github连接-https: //github.com/GeekyPRAVEE/OpenCV-Projects/blob/master/LicensePlateRecoginition.ipynb
交流群
欢迎加入公众号读者群一块儿和同行交流,目前有SLAM、三维视觉、传感器、自动驾驶、计算摄影、检测、分割、识别、医学影像、GAN、算法竞赛等微信群(之后会逐渐细分),请扫描下面微信号加群,备注:”昵称+学校/公司+研究方向“,例如:”张三 + 上海交大 + 视觉SLAM“。请按照格式备注,不然不予经过。添加成功后会根据研究方向邀请进入相关微信群。请勿在群内发送广告,不然会请出群,谢谢理解~
本文分享自微信公众号 - 小白学视觉(NoobCV)。
若有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一块儿分享。