资讯详情

手动搭建一个车牌识别系统 | 附源码

点击上方“”,选择加""或“

重磅干货,第一时间送达  

车牌识别是用来识别不同车辆的图像处理技术。该技术广泛应用于各种安全检测。现在让我一起基于它OpenCV编写Python该任务由代码完成。

车牌识别步骤

1.车牌检测:第一步是从汽车上检测车牌的位置。我们将使用OpenCV找车牌进行中矩形轮廓检测。如果我们知道车牌的确切尺寸、颜色和大致位置,我们可以提高准确性。通常,检测算法也会根据相机的位置和特定国家/地区使用的车牌类型进行训练。但是图像可能不存在汽车。在这种情况下,我们将先进行汽车,然后进行车牌。

2.字符分割:检测到车牌后,我们必须将其切割并保存为新图像。同样,它也可以使用OpenCV来完成。

3. 字符识别:现在,我们在上一步获得的新图像肯定可以写一些字符(数字/字母)。因此,我们可以执行它OCR(光学字符识别)检测数字。

1.车牌检测

让我们以汽车样本图像为例,首先检测汽车上的车牌。然后,我们将使用相同的图像来分割和识别字符。如果您想直接进入代码而无需解释,您可以向下滚动到页面底部,提供完整的代码,或访问以下链接。https://github.com/GeekyPRAVEE/OpenCV-Projects/blob/master/LicensePlateRecoginition.ipynb

如下所示。

图片源链接:https : //rb.gy/lxmiuv

第1步:将图像调整到所需的大小,然后灰度。相同的代码如下

img = cv2.resize(img, (620,480) ) gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) #convert to grey scale 

调整尺寸后,可以避免使用高分辨率图像时出现的以下问题,但要保证调整尺寸后车牌仍保留在框架内。如果在处理图像时不再需要处理颜色细节,灰度变化至关重要,这加快了其他后续处理。完成此步骤后,图像将被这样转换

第二步:每张图片都包含有用和无用的信息。在这种情况下,只有许可证是有用的信息,其余的对我们的程序几乎没用。这种无用的信息被称为噪音。通常,使用双边滤波器(模糊)从图像中删除不必要的细节。

gray = cv2.bilateralFilter(gray, 13, 15, 15) 

语法为destination_image = cv2.bilateralFilter(source_image, diameter of pixel, sigmaColor, sigmaSpace)。我们也可以sigma颜色和sigma为了模糊更多的背景信息,空间从15增加到更高的值,但请注意不要模糊有用的部分。如下图所示,输出图像中的背景细节(树木和建筑物)模糊。这样,我们就可以避免程序处理这些区域。

第三步:下一步是我们实施边缘检测的有趣步骤。有很多方法可以做到,最简单和流行的方法是使用OpenCV中的canny edge方法。执行相同操作的行如下所示

edged = cv2.Canny(gray, 30, 200) #Perform Edge detection 

语法为destination_image = cv2.Canny(source_image,thresholdValue 1,thresholdValue 2)。阈值谷1和阈值2是最小和最大阈值。只显示强度梯度大于最小阈值,小于最大阈值的边缘。图像如下所示

第四步:现在我们可以开始在图像上寻找轮廓了

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在变量中,然后在周围画一个矩形框,以确保我们正确检测到车牌。

第五步:现在我们知道车牌在哪里,剩下的信息对我们几乎没用。因此,除了车牌所在地,我们还可以覆盖整个图片。相同的代码如下所示

# Masking the part other than the number plate 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) 

覆盖的新图像将如下所示

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 plate
text = 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_fever
import cv2
import imutils
import numpy as np
import pytesseract
pytesseract.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 

在「」公众号后台回复:即可下载全网第一份OpenCV扩展模块教程中文版,涵盖等二十多章内容。

在「」公众号后台回复:即可下载包括等31个视觉实战项目,助力快速学校计算机视觉。

在「」公众号后台回复:即可下载含有个基于实现20个,实现OpenCV学习进阶。

交流群

欢迎加入公众号读者群一起和同行交流,目前有SLAM、三维视觉、传感器、自动驾驶、计算摄影、检测、分割、识别、医学影像、GAN、算法竞赛等微信群(以后会逐渐细分),请扫描下面微信号加群,备注:”昵称+学校/公司+研究方向“,例如:”张三 + 上海交大 + 视觉SLAM“。请按照格式备注,否则不予通过。添加成功后会根据研究方向邀请进入相关微信群。在群内发送广告,否则会请出群,谢谢理解~

标签: 数字传感器cz

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台