訂閱
糾錯
加入自媒體

計算機視覺檢測車牌號

2022-02-07 15:48
磐創AI
關注

介紹

在這個技術飛速發展的時代,在尋找一輛犯罪汽車的時候,要停下路上的每一輛車并檢查其車牌是非常困難的。隨著道路欺詐的增加,警察也變得越來越聰明。他們正在使用深度學習和計算機視覺來檢測車牌并從中提取車牌號。今天,我們將建立一個這樣的項目,使用計算機視覺來檢測車牌,這有助于電子挑戰和安全監控。在本博客中,我們將學習如何使用計算機視覺檢測汽車的車牌并提取其值。我們將使用計算機視覺的 OpenCV 庫來檢測汽車的車牌,使用深度學習的 pytesseract 庫來讀取圖像類型并從車牌中獲取字符和數字。最后,我們使用 Tkinter 構建一個圖形用戶界面來顯示我們的項目。

計算機視覺的先決條件

首先,安裝庫:

pip3 install OpenCV-python

pip3 install pytesseract

什么是 OpenCV?

OpenCV 是一個巨大的開源跨平臺庫,它使計算機視覺能夠執行自動駕駛、圖像注釋、基于無人機的作物監測等實際應用。它主要專注于捕獲圖像和視頻以分析重要特征,例如物體檢測、人臉檢測、情緒檢測等,在基于圖像處理的人工智能應用中也發揮著重要作用。

在這里,我們只是使用 openCV 的一些基本特征/功能來識別輸入的汽車圖像中的車牌號。

· 輪廓:輪廓通常被視為邊界像素,因為它們只是簡單的曲線,將邊界中具有相同強度和顏色的所有連續點組合在一起。輪廓的使用在形狀分析、對象檢測和識別、運動檢測以及背景/前景圖像分割中更加清晰。為了減少輪廓檢測的任務,OpenCV 為此提供了內置的 cv2.findContours() 函數。

cv2.findContours(morph_img_threshold,mode=cv2.RETR_EXTERNAL,method=cv2.CHAIN_APPROX_NONE)

我們的 cv.find contours()函數采用三個參數,包括輸入圖像、輪廓檢索模式,最后是輪廓逼近方法。該函數以 Python 列表的形式生成修改后的圖像、層次結構和輪廓。

· 形態變換:是指只對二值圖像進行的一些簡單的操作,并依賴于圖像的形狀。一些常見的形態學操作是 Opening、Closing、Erosion、Dilation。每個函數都有兩個參數,包括輸入圖像和結構元素或內核來決定操作的性質。OpenCV 提供了一些內置函數來執行這些操作:

   · cv2.erode()

   · cv2.dilate()

   · cv2.morphologyEx()

· **高斯模糊:**高斯函數用于對輸入圖像進行模糊和平滑處理,并輸出高斯模糊圖像。它被廣泛用于減少圖像噪聲效果。OpenCV 為此提供了一個內置函數 cv2.GaussianBlur()。

· **Sobel:**此函數用于計算圖像導數,這反過來有助于梯度的計算。OpenCV 為此提供了一個內置函數 cv2.Sobel()。

使用計算機視覺構建車牌的步驟步驟

 1. 導入必要的庫

import numpy as np

import cv2

from PIL import Image

import pytesseract as pytess

步驟 2. 識別不必要的輪廓

現在我們將專注于識別圖片中存在的一些不必要的輪廓,這些輪廓可能會被 OpenCV 錯誤識別,因為它是車牌的可能性很小。

我們將定義三個不同的函數來找到這些輪廓。

1. 首先,我們創建一個名為“ratioCheck”的函數來識別面積范圍和寬高比。

image.png

2. 其次,我們創建一個名為“isMaxWhite”的函數來識別圖像矩陣的平均值:

image.png

3. 最后,我們創建一個名為“ratio_and_rotation”的函數來查找輪廓的旋轉:

image.png

步驟 3 清理識別的車牌

現在我們的任務是創建一個函數,通過刪除所有不必要的元素來準備用于預處理的車牌,并使圖像準備好提供給 pytesseract:

def clean2_plate(plate):

     gray_img = cv2.cvtColor(plate, cv2.COLOR_BGR2GRAY)
            _, thresh_val = cv2.threshold(gray_img, 110, 255, cv2.THRESH_BINARY)

if cv2.waitKey(0) & 0xff == ord('q'):
                   pass
            num_contours,hierarchy = cv2.findContours(thresh_val.copy(),cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)

if num_contours:
                    conto_ar = [cv2.contourArea(c) for c in num_contours]
                    max_cntr_index = np.argmax(conto_ar)
                    max_cnt = num_contours[max_cntr_index]
                    max_cntArea = conto_ar[max_cntr_index]
                    x,y,w,h = cv2.boundingRect(max_cnt)

if not ratioCheck(max_cntArea,w,h):

return plate,None
                    final_img = thresh_val[y:y+h, x:x+w]

return final_img,[x,y,w,h]

else:

return plate, None

第 4 步識別數字和字符

現在我們的任務是以圖像的形式獲取用戶輸入。然后,我們將執行三個討論過的 cv2 函數:Gaussian Blur、Sobel 和形態學運算并識別圖像輪廓,并從每個輪廓中找到循環來識別車牌。最后,將使用 pytesseract 庫并為其提供圖像以提取數字和字符。

img = cv2.imread("testData/img1.jpg")

print("Number  input image...",)

cv2.imshow("input",img)

if cv2.waitKey(0) & 0xff == ord('q'):
          pass

img2 = cv2.GaussianBlur(img, (3,3), 0)

img2 = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY)

img2 = cv2.Sobel(img2,cv2.CV_8U,1,0,ksize=3)   

_,img2 = cv2.threshold(img2,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)

element = cv2.getStructuringElement(shape=cv2.MORPH_RECT, ksize=(17, 3))

morph_img_threshold = img2.copy()

cv2.morphologyEx(src=img2, op=cv2.MORPH_CLOSE, kernel=element, dst=morph_img_threshold)

num_contours, hierarchy= cv2.findContours(morph_img_threshold,mode=cv2.RETR_EXTERNAL,method=cv2.CHAIN_APPROX_NONE)

cv2.drawContours(img2, num_contours, -1, (0,255,0), 1)

for i,cnt in enumerate(num_contours):

    min_rect = cv2.minAreaRect(cnt)

if ratio_and_rotation(min_rect):
                x,y,w,h = cv2.boundingRect(cnt)
                plate_img = img[y:y+h,x:x+w]
                print("Number  identified number plate...")
                cv2.imshow("num plate image",plate_img)

if cv2.waitKey(0) & 0xff == ord('q'):
                    pass

if(isMaxWhite(plate_img)):

             clean_plate, rect = clean2_plate(plate_img)

if rect:
                         fg=0
                         x1,y1,w1,h1 = rect
                         x,y,w,h = x+x1,y+y1,w1,h1
                        # cv2.imwrite("clena.png",clean_plate)
                        plate_im = Image.fromarray(clean_plate)
                        text = tess.image_to_string(plate_im, lang='eng')
                        print("Number  Detected Plate Text : ",text)

項目 GUI 代碼

現在我們將為圖形用戶界面創建一個名為“gui.py”的 python 文件,以創建一個接受圖像作為輸入并在屏幕上輸出車牌號的web表單。

import tkinter as tk #python library for GUI

from tkinter import filedialog

from tkinter import *

from PIL import ImageTk, Image

from tkinter import PhotoImage

import numpy as np

import cv2

import pytesseract as tess

def clean2_plate(plate):#to clean the identified number plate using above discussed openCV methods
            gray_img = cv2.cvtColor(plate, cv2.COLOR_BGR2GRAY)
           _, thresh_val = cv2.threshold(gray_img, 110, 255, cv2.THRESH_BINARY)
            num_contours,hierarchy = cv2.findContours(thresh_val.copy(),cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)

if num_contours:
                 conto_ar = [cv2.contourArea(c) for c in num_contours]
                 max_cntr_index = np.argmax(conto_ar)
                 max_cnt = num_contours[max_cntr_index]
                 max_cntArea = conto_ar[max_cntr_index]
                 x,y,w,h = cv2.boundingRect(max_cnt)

if not ratioCheck(max_cntArea,w,h):

return plate,None
                 final_img = thresh_val[y:y+h, x:x+w]

return final_img,[x,y,w,h]

else:

return plate,None

#method to identify the range of area and ratio between width and height

def ratioCheck(Ar, breatth, height):
           ratio = float(breatth) / float(height)

if ratio < 1:
                  ratio = 1 / ratio

if (Ar  73862.5) or (ratio  6):

return False

return True

#method to identify average of image matrix:

def isMaxWhite(plate):

    avg = np.mean(plate)

if(avg>=115):

return True

else:

return False

# to find the rotation of contours:

def ratio_and_rotation(rect):

  (x, y), (breatth, height), rect_angle = rect

if(breatth>height):

      angle = -rect_angle

else:

      angle = 90 + rect_angle

if angle>15:

return False

if height == 0 or breatth == 0:

return False

  Ar = height*breatth#area calculation

if not ratioCheck(Ar,breatth,height):

return False

else:

return True

top=tk.Tk()

top.geometry('900x700')#window size

top.title('Number Plate Recognition')#title of GUI

top.iconphoto(True, PhotoImage(file="/home/shikha/GUI/logo.png"))#give the path of folder where your test image is available

img = ImageTk.PhotoImage(Image.open("logo.png"))#to open your image

top.configure(background='#CDCDCD')#background color

label=Label(top,background='#CDCDCD', font=('arial',35,'bold'))#to set background,font,and size of the label

sign_image = Label(top,bd=10)

plate_image=Label(top,bd=10)

def classify(file_path):

  res_text=[0]

  res_img=[0]

  img = cv2.imread(file_path)

  img2 = cv2.GaussianBlur(img, (3,3), 0)

  img2 = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY)

  img2 = cv2.Sobel(img2,cv2.CV_8U,1,0,ksize=3)   

  _,img2 = cv2.threshold(img2,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)

  element = cv2.getStructuringElement(shape=cv2.MORPH_RECT, ksize=(17, 3))

  morph_img_threshold = img2.copy()

  cv2.morphologyEx(src=img2, op=cv2.MORPH_CLOSE, kernel=element, dst=morph_img_threshold)

  num_contours, hierarchy= cv2.findContours(morph_img_threshold,mode=cv2.RETR_EXTERNAL,method=cv2.CHAIN_APPROX_NONE)

  cv2.drawContours(img2, num_contours, -1, (0,255,0), 1)

for i,cnt in enumerate(num_contours):

      min_rect = cv2.minAreaRect(cnt)

if ratio_and_rotation(min_rect):

          x,y,w,h = cv2.boundingRect(cnt)

          plate_img = img[y:y+h,x:x+w]

          print("Number  identified number plate...")

          res_img[0]=plate_img

          cv2.imwrite("result.png",plate_img)

#method to identify average of image matrix:

if(isMaxWhite(plate_img)):

              clean_plate, rect = clean2_plate(plate_img)

if rect:

                  fg=0

                  x1,y1,w1,h1 = rect

                  x,y,w,h = x+x1,y+y1,w1,h1

                 plate_im = Image.fromarray(clean_plate)

                  text = tess.image_to_string(plate_im, lang='eng')

                  res_text[0]=text

if text:

                      break

  label.configure(foreground='#011638', text=res_text[0])

  uploaded=Image.open("result.png")

  im=ImageTk.PhotoImage(uploaded)

  plate_image.configure(image=im)

  plate_image.image=im

  plate_image.pack()

  plate_image.place(x=560,y=320)

def show_classify_button(file_path):

  classify_b=Button(top,text="Classify Image",command=lambda: classify(file_path),padx=10,pady=5)

  classify_b.configure(background='#364156', foreground='white',font=('arial',15,'bold'))

  classify_b.place(x=490,y=550)

def upload_image():

try:

      file_path=filedialog.askopenfilename()

      uploaded=Image.open(file_path)

      uploaded.thumbnail(((top.winfo_width()/2.25),(top.winfo_height()/2.25)))

      im=ImageTk.PhotoImage(uploaded)

      sign_image.configure(image=im)

      sign_image.image=im

      label.configure(text='')

      show_classify_button(file_path)

except:

      pass

upload=Button(top,text="Upload an image",command=upload_image,padx=10,pady=5)

upload.configure(background='#364156', foreground='white',font=('arial',15,'bold'))

upload.pack()

upload.place(x=210,y=550)

sign_image.pack()

sign_image.place(x=70,y=200)

label.pack()

label.place(x=500,y=220)

heading = Label(top,image=img)

heading.configure(background='#CDCDCD',foreground='#364156')

heading.pack()

top.mainloop()

計算機視覺輸出

結論在這篇博客中,我們使用計算機視覺和深度學習來創建一個車牌識別和牌照號碼提取系統。在這里,我們創建了一個 GUI 來上傳車輛的圖像并識別編號。我們主要關注兩個庫:OpenCV 來清理車牌, pytesseract 識別車牌數字和字符。我們還學習了 OpenCV 的一些特殊功能,即形態變換、高斯模糊和 Sobel 算子。

       原文標題 : 計算機視覺檢測車牌號

聲明: 本文由入駐維科號的作者撰寫,觀點僅代表作者本人,不代表OFweek立場。如有侵權或其他問題,請聯系舉報。

發表評論

0條評論,0人參與

請輸入評論內容...

請輸入評論/評論長度6~500個字

您提交的評論過于頻繁,請輸入驗證碼繼續

暫無評論

暫無評論

    人工智能 獵頭職位 更多
    掃碼關注公眾號
    OFweek人工智能網
    獲取更多精彩內容
    文章糾錯
    x
    *文字標題:
    *糾錯內容:
    聯系郵箱:
    *驗 證 碼:

    粵公網安備 44030502002758號