點擊上方「小白學視覺」,選擇加"星標"或「置頂」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源創計劃」,歡迎正在閱讀的你也加入,一塊兒分享。