訂閱
糾錯(cuò)
加入自媒體

計(jì)算機(jī)視覺檢測車牌號(hào)

介紹

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

計(jì)算機(jī)視覺的先決條件

首先,安裝庫:

pip3 install OpenCV-python

pip3 install pytesseract

什么是 OpenCV?

OpenCV 是一個(gè)巨大的開源跨平臺(tái)庫,它使計(jì)算機(jī)視覺能夠執(zhí)行自動(dòng)駕駛、圖像注釋、基于無人機(jī)的作物監(jiān)測等實(shí)際應(yīng)用。它主要專注于捕獲圖像和視頻以分析重要特征,例如物體檢測、人臉檢測、情緒檢測等,在基于圖像處理的人工智能應(yīng)用中也發(fā)揮著重要作用。

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

· 輪廓:輪廓通常被視為邊界像素,因?yàn)樗鼈冎皇呛唵蔚那,將邊界中具有相同強(qiáng)度和顏色的所有連續(xù)點(diǎn)組合在一起。輪廓的使用在形狀分析、對象檢測和識(shí)別、運(yùn)動(dòng)檢測以及背景/前景圖像分割中更加清晰。為了減少輪廓檢測的任務(wù),OpenCV 為此提供了內(nèi)置的 cv2.findContours() 函數(shù)。

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

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

· 形態(tài)變換:是指只對二值圖像進(jìn)行的一些簡單的操作,并依賴于圖像的形狀。一些常見的形態(tài)學(xué)操作是 Opening、Closing、Erosion、Dilation。每個(gè)函數(shù)都有兩個(gè)參數(shù),包括輸入圖像和結(jié)構(gòu)元素或內(nèi)核來決定操作的性質(zhì)。OpenCV 提供了一些內(nèi)置函數(shù)來執(zhí)行這些操作:

   · cv2.erode()

   · cv2.dilate()

   · cv2.morphologyEx()

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

· **Sobel:**此函數(shù)用于計(jì)算圖像導(dǎo)數(shù),這反過來有助于梯度的計(jì)算。OpenCV 為此提供了一個(gè)內(nèi)置函數(shù) cv2.Sobel()。

使用計(jì)算機(jī)視覺構(gòu)建車牌的步驟步驟

 1. 導(dǎo)入必要的庫

import numpy as np

import cv2

from PIL import Image

import pytesseract as pytess

步驟 2. 識(shí)別不必要的輪廓

現(xiàn)在我們將專注于識(shí)別圖片中存在的一些不必要的輪廓,這些輪廓可能會(huì)被 OpenCV 錯(cuò)誤識(shí)別,因?yàn)樗擒嚺频目赡苄院苄 ?/p>

我們將定義三個(gè)不同的函數(shù)來找到這些輪廓。

1. 首先,我們創(chuàng)建一個(gè)名為“ratioCheck”的函數(shù)來識(shí)別面積范圍和寬高比。

image.png

2. 其次,我們創(chuàng)建一個(gè)名為“isMaxWhite”的函數(shù)來識(shí)別圖像矩陣的平均值:

image.png

3. 最后,我們創(chuàng)建一個(gè)名為“ratio_and_rotation”的函數(shù)來查找輪廓的旋轉(zhuǎn):

image.png

步驟 3 清理識(shí)別的車牌

現(xiàn)在我們的任務(wù)是創(chuàng)建一個(gè)函數(shù),通過刪除所有不必要的元素來準(zhǔn)備用于預(yù)處理的車牌,并使圖像準(zhǔn)備好提供給 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.a(chǎn)rgmax(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 步識(shí)別數(shù)字和字符

現(xiàn)在我們的任務(wù)是以圖像的形式獲取用戶輸入。然后,我們將執(zhí)行三個(gè)討論過的 cv2 函數(shù):Gaussian Blur、Sobel 和形態(tài)學(xué)運(yùn)算并識(shí)別圖像輪廓,并從每個(gè)輪廓中找到循環(huán)來識(shí)別車牌。最后,將使用 pytesseract 庫并為其提供圖像以提取數(shù)字和字符。

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)

項(xiàng)目 GUI 代碼

現(xiàn)在我們將為圖形用戶界面創(chuàng)建一個(gè)名為“gui.py”的 python 文件,以創(chuàng)建一個(gè)接受圖像作為輸入并在屏幕上輸出車牌號(hào)的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.a(chǎn)rgmax(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.a(chǎn)skopenfilename()

      uploaded=Image.open(file_path)

      uploaded.thumbnail(((top.winfo_width()/2.25),(top.winfo_h(yuǎn)eight()/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()

計(jì)算機(jī)視覺輸出

結(jié)論在這篇博客中,我們使用計(jì)算機(jī)視覺和深度學(xué)習(xí)來創(chuàng)建一個(gè)車牌識(shí)別和牌照號(hào)碼提取系統(tǒng)。在這里,我們創(chuàng)建了一個(gè) GUI 來上傳車輛的圖像并識(shí)別編號(hào)。我們主要關(guān)注兩個(gè)庫:OpenCV 來清理車牌, pytesseract 識(shí)別車牌數(shù)字和字符。我們還學(xué)習(xí)了 OpenCV 的一些特殊功能,即形態(tài)變換、高斯模糊和 Sobel 算子。

       原文標(biāo)題 : 計(jì)算機(jī)視覺檢測車牌號(hào)

聲明: 本文由入駐維科號(hào)的作者撰寫,觀點(diǎn)僅代表作者本人,不代表OFweek立場。如有侵權(quán)或其他問題,請聯(lián)系舉報(bào)。

發(fā)表評(píng)論

0條評(píng)論,0人參與

請輸入評(píng)論內(nèi)容...

請輸入評(píng)論/評(píng)論長度6~500個(gè)字

您提交的評(píng)論過于頻繁,請輸入驗(yàn)證碼繼續(xù)

  • 看不清,點(diǎn)擊換一張  刷新

暫無評(píng)論

暫無評(píng)論

人工智能 獵頭職位 更多
掃碼關(guān)注公眾號(hào)
OFweek人工智能網(wǎng)
獲取更多精彩內(nèi)容
文章糾錯(cuò)
x
*文字標(biāo)題:
*糾錯(cuò)內(nèi)容:
聯(lián)系郵箱:
*驗(yàn) 證 碼:

粵公網(wǎng)安備 44030502002758號(hào)