車牌識別分三步:車牌定位,車牌字符分割,車牌字符識別。
本篇就車牌定位進行講述。車牌定位顧名思義——找出車牌的位置。如何實現,又分三步:圖像預處理,數學形態學粗定位,長寬比例精確定位。
首先,對圖像預處理:
彩色圖像轉灰度圖高斯濾波,中值濾波邊緣化檢測二值化操作
#-*- coding: utf-8 -*-
import cv2
import numpy as npdef Process(img):# 高斯平滑gaussian = cv2.GaussianBlur(img, (3, 3), 0, 0, cv2.BORDER_DEFAULT)#cv2.GaussianBlur(src,ksize,sigmaX[,sigmaxY[,borderType]]])高斯濾波函數#src: 輸入圖像#ksize: 高斯內核大小,元組類型#sigmaX: 高斯核函數在X方向上的標準偏差#sigmaY: 高斯核函數在Y方向上的標準偏差,如果sigmaY是0,則函數會自動將sigmaY的值設置為與sigmaX相同的值,如果sigmaX和sigmaY都是0,這兩個值將由ksize[0]和ksize[1]計算而來。建議將size、sigmaX和sigmaY都指定出來。#borderType: 推斷圖像外部像素的某種便捷模式,有默認值cv2.BORDER_DEFAULT,如果沒有特殊需要不用更改,具體可以參考borderInterpolate()函數。# 中值濾波median = cv2.medianBlur(gaussian, 5)#cv2.medianBlur(src,ksize)#src: 輸入圖像#ksize: 高斯內核大小,元組類型# Sobel算子# 梯度方向: xsobel = cv2.Sobel(median, cv2.CV_8U, 1, 0, ksize=3)# 利用Sobel方法可以進行sobel邊緣檢測# img表示源圖像,即進行邊緣檢測的圖像# 圖像深度是cv2.CV_8U、cv2.CV_16U、cv2.CV_16S、cv2.CV_32F以及cv2.CV_64F其中的某一個# 第三和第四個參數分別是對X和Y方向的導數(即dx,dy),對于圖像來說就是差分,這里1表示對X求偏導(差分),0表示不對Y求導(差分)。其中,X還可以求2次導。# 注意:對X求導就是檢測X方向上是否有邊緣。# 第五個參數ksize是指核的大小。# 這里說明一下,這個參數的前四個參數都沒有給誰賦值,而ksize則是被賦值的對象# 實際上,這是可省略的參數,而前四個是不可省的參數。注意其中的不同點值化ret, binary = cv2.threshold(sobel, 170, 255, cv2.THRESH_BINARY)#灰度值小于175的點置0,灰度值大于175的點置255#最后的參數是閾值類型,對應一個公式,一般用這個就可以
然后,數學形態學處理: 形態學處理的核心就是定義結構元素,一般情況下對二值化圖像進行的操作。
# 膨脹和腐蝕操作的核函數element1 = cv2.getStructuringElement(cv2.MORPH_RECT, (9, 1))element2 = cv2.getStructuringElement(cv2.MORPH_RECT, (9, 7))#第一個參數定義結構元素,如橢圓(MORPH_ELLIPSE)、交叉形結構(MORPH_CROSS)和矩形(MORPH_RECT)#第二個參數就是指和函數的size,9×1# 膨脹一次,讓輪廓突出dilation = cv2.dilate(binary, element2, iterations=1)# 腐蝕一次,去掉細小雜點erosion = cv2.erode(dilation, element1, iterations=1)# 再次膨脹,讓輪廓更明顯dilation2 = cv2.dilate(erosion, element2, iterations=3)#存儲中間圖片 cv2.imwrite("binary.png", binary)cv2.imwrite("dilation.png", dilation)cv2.imwrite("erosion.png", erosion)cv2.imwrite("dilation2.png", dilation2)return dilation2
最后:查找輪廓,精確定位
查找篩選輪廓車牌長寬比顏色判斷(沒大必要)
def GetRegion(img):regions = []# 查找輪廓_, contours, hierarchy = cv2.findContours(img, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)#三個輸入參數:輸入圖像(二值圖像),輪廓檢索方式,輪廓近似方法#輪廓檢索方式:cv2.RETR_EXTERNAL 只檢測外輪廓。cv2.RETR_LIST 檢測的輪廓不建立等級關系。cv2.RETR_CCOMP 建立兩個等級的輪廓,上面一層為外邊界,里面一層為內孔的邊界信息。cv2.RETR_TREE 建立一個等級樹結構的輪廓#輪廓近似方法:cv2.CHAIN_APPROX_NONE 存儲所有邊界點。cv2.CHAIN_APPROX_SIMPLE 壓縮垂直、水平、對角方向,只保留端點。cv2.CHAIN_APPROX_TX89_L1 使用teh-Chini近似算法。cv2.CHAIN_APPROX_TC89_KCOS 使用teh-Chini近似算法#三個返回值:圖像,輪廓,輪廓的層析結構#篩選面積小的for contour in contours:#計算該輪廓的面積area = cv2.contourArea(contour)#面積小的都篩選掉if (area < 2000):continue#輪廓近似,作用很小epslion = 1e-3 * cv2.arcLength(contour, True)approx = cv2.approxPolyDP(contour, epslion, True)#epsilon,是從輪廓到近似輪廓的最大距離。是一個準確率參數,好的epsilon的選擇可以得到正確的輸出。True決定曲線是否閉合。# 找到最小的矩形,該矩形可能有方向rect = cv2.minAreaRect(contour)# box是四個點的坐標box = cv2.boxPoints(rect)box = np.int0(box)## 計算高和寬height = abs(box[0][1] - box[2][1])width = abs(box[0][0] - box[2][0])#車牌正常情況下長高比在2-5之間ratio =float(width) / float(height)if (ratio < 5 and ratio > 2):regions.append(box)return regionsdef detect(img):# 灰度化gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)# 預處理及形態學處理,得到可以查找矩形的圖片prc = Process(gray)#得到車牌輪廓regions = GetRegion(prc)print('[INFO]:Detect %d license plates' % len(regions))#用綠線畫出這些找到的輪廓for box in regions:cv2.drawContours(img, [box], 0, (0, 255, 0), 2)#五個輸入參數:原始圖像,輪廓,輪廓的索引(當設置為-1時,繪制所有輪廓),畫筆顏色,畫筆大小#一個返回值:返回繪制了輪廓的圖像cv2.imshow('Result', img)#保存結果文件名cv2.imwrite('result.jpg', img)cv2.waitKey(0)cv2.destroyAllWindows()if __name__ == '__main__':#輸入的參數為圖片的路徑img = cv2.imread('1.jpg')detect(img)
總結
以上是生活随笔為你收集整理的车牌识别(一)——车牌定位(附详细代码及注释)的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。