如何使用OpenCv和Pytesseract进行车牌检测和识别

495 阅读7分钟

使用OpenCv和Pytesseract进行车牌检测和识别

车牌检测是指识别汽车上被预测为车牌的部分。识别是指识别构成车牌的数值。

车牌检测和识别是利用计算机视觉从汽车的输入图像中检测和识别车牌的技术。

这项技术适用于许多领域。在道路上,它被用来识别违反交通规则的汽车。在安全方面,它被用来捕捉进出某些场所的车辆的车牌。在停车场,它被用来捕捉正在停放的汽车的车牌。它的应用清单不胜枚举。

简介

Python使我们有能力创建我们的车牌检测和识别程序。我们通过使用它的三个库来实现这一点;pytesseract、imutils和OpenCv。

在本教程中,我们将学习软件检测和识别车牌的过程,如何使用我们上面提到的三个库来创建我们的程序,最后是如何创建一个能够检测和识别车牌的程序。我们将使用pycharm社区版作为我们的IDE,因为它可以在互联网上免费获得。使用Windows或Linux的人可以跟进。

前提条件

要完成本教程,读者需要:

  • 熟悉python编程语言
  • 在他们的电脑上安装了pycharm

软件在检测和识别车牌时经历的过程

软件要检测和识别车牌,需要经历三个主要过程。

  • 将汽车的图像作为输入--程序接收要检测的车牌的输入。
  • 处理输入--对作为输入的图像进行处理,以检测汽车中作为车牌的部分。
  • 识别车牌 - 从车牌图像中提取检测到的车牌值。

创建一个车牌检测和识别程序

首先,让我们准备一下我们的工作空间。打开pycharm,点击创建一个新项目,如下图所示。Pycharm

在接下来出现的窗口中,点击创建。

现在我们需要安装创建程序所需的Python库。为了达到这个目的,打开终端,输入以下命令,然后点击回车。

pip install opencv-contrib-python

等待几秒钟,直到它被成功安装。我们也把这个库称为cv2。我们将用它来预处理我们的图像,同时显示经过处理的图像。

下面的截图显示了如何从终端安装cv2。

Terminal

我们将按照同样的步骤来安装其他两个库。我们将只改变命令的部分。

要安装imutils ,请使用以下命令。

pip install imutils

我们将需要这个库来调整我们的图像大小。

要安装pytesseract ,使用下面的命令。

pip install pytesseract

我们将需要这个库来从检测到的车牌中提取车牌文本。

我们现在还需要一个东西,那就是魔方。这是pytesseract用来识别图像中字符的软件。

安装tesseract
我们将检测和识别车牌的图像

Test

我们将使用上述图片作为我们程序的输入。

现在让我们进入编码的乐趣部分。在Pycharm自动创建的main.py 文件中输入以下代码。

导入我们需要的库
import cv2
import imutils
import pytesseract

在上面的代码中,我们正在导入我们讨论过的每个库。这将使我们能够使用我们将需要的他们的一些功能。

指定tesseract的安装路径
pytesseract.pytesseract.tesseract_cmd = 'C:\Program Files\Tesseract-OCR\\tesseract'

在上面的代码中:'C:\Program Files\Tesseract-OCR\\tesseract' 是我们安装tesseract的路径。用你的路径替换这部分。

接收我们的图片输入并将其宽度调整为300像素
image = cv2.imread('test.jpg')
image = imutils.resize(image, width=300 )
cv2.imshow("original image", image)
cv2.waitKey(0)
  • image = cv2.imread('test.jpg'):我们将图片作为我们的输入。test.jpg 是图片的名称。请自由地用你自己的名字替换它。
  • image = imutils.resize(image, width=300 ):我们正在调整图片的大小。image 是我们输入的图片。对于width=300 ,我们将该图像的宽度调整为300像素。
  • cv2.imshow("original image", image):original image 是显示图像的窗口的名称。请随意给它起个名字。
  • cv2.waitKey(0):我们在等待键盘上的任何键被按下,以继续执行下面的代码。
将输入的图像转换为灰度
gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
cv2.imshow("greyed image", gray_image)
cv2.waitKey(0)
  • gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY):我们正在创建一个变量gray_image 。然后我们将我们的输入图像传递给cv2.cvtColorcv2.COLOR_BGR2GRAY ,指定该图像应被转换为灰度图像。
  • cv2.imshow("greyed image", gray_image):我们正在显示已经转换为灰度的图像。
减少灰度图像中的噪音
gray_image = cv2.bilateralFilter(gray_image, 11, 17, 17) 
cv2.imshow("smoothened image", gray_image)
cv2.waitKey(0)
  • gray_image = cv2.bilateralFilter(gray_image, 11, 17, 17):我们正在减少灰度图像中的噪音,从而使它变得平滑。
  • cv2.imshow("smoothened image", gray_image):显示已经平滑化的图像。
检测平滑后的图像的边缘
edged = cv2.Canny(gray_image, 30, 200) 
cv2.imshow("edged image", edged)
cv2.waitKey(0)
  • edged = cv2.Canny(gray_image, 30, 200):我们正在创建变量edged 。然后我们将平滑化的图像传给cv2.canny ,以检测其中的边缘。
  • cv2.imshow("edged image", edged):我们将显示带有检测到的边缘的图像。
从有边缘的图像中寻找轮廓线
cnts,new = cv2.findContours(edged.copy(), cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
image1=image.copy()
cv2.drawContours(image1,cnts,-1,(0,255,0),3)
cv2.imshow("contours",image1)
cv2.waitKey(0)
  • cnts:这代表了轮廓线。
  • RETR_LIST:它检索了所有的轮廓线,但没有建立任何父子关系。
  • CHAIN_APPROX_SIMPLE:移除检测到的轮廓线上的所有冗余点。
  • image1=image.copy():我们正在制作一个原始输入图像的副本。这是因为我们不希望改变原始图像。
  • cv2.drawContours(image1,cnts,-1,(0,255,0),3):我们要在我们的图像上画出识别的轮廓。按原样输入数值。
  • cv2.imshow("contours",image1):我们正在显示周围画有识别轮廓的图像。
对识别的轮廓线进行排序
cnts = sorted(cnts, key = cv2.contourArea, reverse = True) [:30]
screenCnt = None
image2 = image.copy()
cv2.drawContours(image2,cnts,-1,(0,255,0),3)
cv2.imshow("Top 30 contours",image2)
cv2.waitKey(0)
  • cnts = sorted(cnts, key = cv2.contourArea, reverse = True) [:30]:我们根据最小面积30来对等高线进行排序,并忽略低于此面积的等高线。
  • screenCnt = None:存储号码牌的轮廓线。
  • cv2.drawContours(image2,cnts,-1,(0,255,0),3):在图像上画出分类后的轮廓线。
  • cv2.imshow("Top 30 contours",image2):显示包含前30个轮廓线的图像,在其周围绘制。
寻找有四条边的轮廓线
i=7
for c in cnts:
        perimeter = cv2.arcLength(c, True)
        approx = cv2.approxPolyDP(c, 0.018 * perimeter, True)
        if len(approx) == 4: 
                screenCnt = approx
  • for c in cnts:: 我们在我们做了排序的轮廓线上创建一个for循环。这是为了找到我们所期望的号码牌的最佳轮廓线。
  • perimeter = cv2.arcLength(c, True):周长也被称为arclength。我们正在使用arclength函数来寻找它。
  • cv2.approxPolyDP(c, 0.018 * perimeter, True):ApproxPolyDP可以精确地逼近多边形的曲线。
  • if len(approx) == 4:: 选择有四条边的轮廓线,因为这可能是我们的车牌。
裁剪确定为车牌的长方形部分
x,y,w,h = cv2.boundingRect(c) 
new_img=image[y:y+h,x:x+w]
cv2.imwrite('./'+str(i)+'.png',new_img)
i+=1
break
  • x,y,w,h = cv2.boundingRect(c):这就找到了确定为车牌的部分的坐标。
  • cv2.imwrite('./'+str(i)+'.png',new_img:存储裁剪后的车牌的新图像。
  • break:打破for循环。
在原始图像上绘制选定的轮廓线
cv2.drawContours(image, [screenCnt], -1, (0, 255, 0), 3)
cv2.imshow("image with detected license plate", image)
cv2.waitKey(0)
  • cv2.drawContours(image, [screenCnt], -1, (0, 255, 0), 3):这将在我们的原始图像上画出被选择为车牌的轮廓线。
  • cv2.imshow("image with detected license plate", image):显示在车牌上画有轮廓的最终图像。
从裁剪后的车牌图像中提取文本
Cropped_loc = './7.png'
cv2.imshow("cropped", cv2.imread(Cropped_loc))
plate = pytesseract.image_to_string(Cropped_loc, lang='eng')
print("Number plate is:", plate)
cv2.waitKey(0)
cv2.destroyAllWindows()
  • Cropped_loc = './7.png':这是剪裁后的车牌图像的文件名。
  • cv2.imshow("cropped", cv2.imread(Cropped_loc)):我们正在显示裁剪后的车牌部分的图像。
  • plate = pytesseract.image_to_string(Cropped_loc, lang='eng'):我们正在传递车牌裁剪部分的图像。然后我们调用pytesseract来提取图片上的文字。
  • print("Number plate is:", plate):我们将打印出提取的文本。
  • cv2.destroyAllWindows():我们正在关闭所有打开的窗口。

结果

当程序成功运行后,其输出结果如下。

Results

结论

你现在掌握了创建一个检测和识别车牌的程序所需的所有技能。捕捉更多的车辆图像并将它们输入程序,然后坐下来,看着程序发挥它的魔力。