一、車牌識(shí)別研究現(xiàn)狀與分析
車牌識(shí)別系統(tǒng)廣泛應(yīng)用于交通管理、收費(fèi)站、城市交叉口、港口和機(jī)場(chǎng)、機(jī)動(dòng)車檢測(cè)、停車場(chǎng)管理等不同的場(chǎng)所,對(duì)提高這些場(chǎng)所交通系統(tǒng)的管理水平和自動(dòng)化程度具有重要的意義[1]。車牌自動(dòng)識(shí)別系統(tǒng)主要包括車牌定位、車牌分割、車牌字符識(shí)別三部分。
其中,僅就車牌字符識(shí)別而言,目前基于神經(jīng)網(wǎng)絡(luò)、字符筆畫特征和模糊識(shí)別等方法能夠有效地識(shí)別解析度較高和圖像較為清晰的車牌。時(shí)下,根據(jù)車牌特征信息分析的車牌識(shí)別方法也已陸續(xù)問(wèn)世,如文獻(xiàn)[2]中,充分利用車牌定位和字符分割過(guò)程中得到的信息對(duì)車牌識(shí)別過(guò)程進(jìn)行反饋,將二值化、車牌定位和字符分割緊密結(jié)合,注重車牌與車輛背景圖像分離特征,以連通域分析為字符分割特點(diǎn),提高正確率。文獻(xiàn)[3]采用徑向基神經(jīng)網(wǎng)絡(luò)(RBFNN)識(shí)別車牌,RBFNN的算法采用混合結(jié)構(gòu)優(yōu)化算法,在識(shí)別中使用非全字符輸入和多層識(shí)別器?;旌辖Y(jié)構(gòu)優(yōu)化算法簡(jiǎn)化了RBFNN的結(jié)構(gòu),提高了RBFNN的泛化能力; 非全字符簡(jiǎn)化了RBFNN的輸入,提高了車牌識(shí)別的速度; 多層識(shí)別器保證了非全字符輸入的識(shí)別率。將RBFNN的混合結(jié)構(gòu)算法和非全字符輸入、多層識(shí)別器相結(jié)合,在保證識(shí)別率的基礎(chǔ)上,提高了識(shí)別速度。文獻(xiàn)[3]中的仿真試驗(yàn)表明: 相對(duì)于全字符輸入的車牌識(shí)別,該方法在時(shí)間復(fù)雜度上的表現(xiàn)非常優(yōu)秀; 相對(duì)于K-means算法的RBFNN車牌識(shí)別,其方法在泛化能力上有一定的優(yōu)勢(shì)。
二、車牌識(shí)別算法原理
2.1 車牌定位
當(dāng)人們從遠(yuǎn)處觀察車輛時(shí),判別牌照區(qū)域的主要依據(jù)是車牌的顏色、亮度和車牌字符的邊緣形成的紋理。所以,充分利用這些信息就成了定位車牌的關(guān)鍵。牌照區(qū)域有別于其他區(qū)域的地方就在于牌照上有字符,結(jié)合國(guó)內(nèi)車牌的特征,國(guó)內(nèi)的汽車牌照內(nèi)容由數(shù)字、字母和漢字組成。首位字符是漢字部分,其次是24個(gè)英文字符中的一個(gè) (字母O和I除外),后面五位是數(shù)字和字母的組合。
根據(jù)中國(guó)車牌字符的特征制作模板,使用模板匹配的方法來(lái)識(shí)別字符的識(shí)別率較高。圖像的灰度水平投影具有較好的連續(xù)性,不會(huì)有大的起伏,體現(xiàn)在紋理信息上就是其垂直邊緣的間距呈現(xiàn)出相應(yīng)規(guī)律[4]。
2.1.1 基于RGB閾值的車牌區(qū)域初定位
在本次課程設(shè)計(jì)中,采用的是車牌定位中較為簡(jiǎn)單的基于RGB圖像閾值的車牌定位方法。查閱資料得知,正常光線強(qiáng)度情況下,車牌藍(lán)色的RGB分量值如 表1 所示:
分量 | 藍(lán)色 |
---|---|
R | 23 |
G | 63 |
B | 138 |
但在大多數(shù)情況下,采集到的車牌圖像是不能保證正常曝光的,因此需要預(yù)設(shè)一個(gè)閾值以保證不在正常曝光下的車牌區(qū)域也能被定位到。計(jì)算圖像的每個(gè)像素點(diǎn)的RGB值與正常曝光下的車牌藍(lán)色RGB值之間的差值,若在閾值范圍之內(nèi),則認(rèn)定是車牌區(qū)域;若超過(guò)閾值,則認(rèn)定不是車牌區(qū)域。依據(jù)該方法,可以從采集到的輸入圖像中獲取疑似車牌的區(qū)域,該區(qū)域可能存在多個(gè),許多符合條件的非車牌區(qū)域像素點(diǎn)也有可能存在其中,接下來(lái)需要用形態(tài)學(xué)的方法進(jìn)一步處理定位出的車牌以獲取最終的牌照區(qū)域。
2.1.2 基于數(shù)學(xué)形態(tài)學(xué)的車牌初定位區(qū)域連通處理
如果僅僅依靠藍(lán)色的RGB分量值來(lái)定位車牌位置的話,由于外界的光線強(qiáng)度孰強(qiáng)孰弱、采集到的圖像中也有可能存有藍(lán)色區(qū)域等干擾因素,使得定位出的車牌位置可能存在多個(gè),非常難確定正確的車牌區(qū)域。所以,需要用數(shù)學(xué)形態(tài)學(xué)的相關(guān)操作對(duì)圖像做相應(yīng)的處理以為后續(xù)的篩選過(guò)程做準(zhǔn)備。首先對(duì)圖像做膨脹操作,目的是將車牌區(qū)域的各個(gè)字符連接為一個(gè)整體,然后再對(duì)輸入圖像作形態(tài)學(xué)腐蝕操作,目的是去掉圖像中孤立的噪聲點(diǎn)。經(jīng)形態(tài)學(xué)操作處理輸入圖像之后,車牌區(qū)域會(huì)被規(guī)劃成一個(gè)較為規(guī)整的傾斜的長(zhǎng)方形區(qū)域。
2.1.3 車牌的精確定位
經(jīng)形態(tài)學(xué)方法處理之后,圖中絕大多數(shù)孤立的噪聲點(diǎn)已被清除,且車牌區(qū)域呈現(xiàn)出一個(gè)較為規(guī)則的矩形。由于數(shù)學(xué)形態(tài)學(xué)處理會(huì)減少車牌的信息以及車牌區(qū)域發(fā)生傾斜等原因,所以預(yù)設(shè)車牌的寬高比例會(huì)比正常情況下的比例范圍要更大,設(shè)定寬高比例閾值為2.0-5.5,最小面積為200。根據(jù)車牌的寬高比例以及預(yù)設(shè)的最小面積等特征,將不符合條件的可疑矩形區(qū)域排除掉,剩下的矩形區(qū)域就是車牌區(qū)域,并在原始圖像上用紅色邊框表示。
2.1.4 相關(guān)參考博客
汽車車牌識(shí)別系統(tǒng)實(shí)現(xiàn)(二)–車牌定位+代碼實(shí)現(xiàn)_奮斗丶的博客-CSDN博客_車牌識(shí)別代碼實(shí)現(xiàn)
車牌分割實(shí)戰(zhàn)_勇敢牛牛@的博客-CSDN博客
2.2 車牌分割
2.2.1 車牌區(qū)域角點(diǎn)校正
在進(jìn)行車牌分割任務(wù)之前,需進(jìn)行車牌區(qū)域的角點(diǎn)校正。由于拍攝車牌的相機(jī)位置原因,拍攝得到的圖像有極大可能是存在畸變的,因而有必要在進(jìn)行車牌字符分割之前先進(jìn)行車牌區(qū)域圖像的去畸變。
通常去畸變采用的是透視變換 (Perspective Transformation) 方法。透視變換是將圖片投影到一個(gè)新的視平面 (Viewing Plane),也稱作投影映射 (Projective Mapping)。透視變換的目的就是把現(xiàn)實(shí)中為直線的物體,在圖片上可能呈現(xiàn)為斜線,通過(guò)透視變換轉(zhuǎn)換成直線的變換。opencv-python 也提供了十分方便的圖像去畸變方案,通過(guò) cv2.getPerspectiveTransform()
函數(shù)獲取透視變換矩陣后,再通過(guò) cv2.warpPerspective()
函數(shù)即可實(shí)現(xiàn)透視變換,將包含畸變的車牌圖像進(jìn)行相應(yīng)的校正。
參考博客:【代碼篇】opencv實(shí)現(xiàn)圖像校正(python版)_Zero_0-1的博客-CSDN博客_python圖片梯形校正
2.2.2 基于投影的車牌字符分割
車牌分割的好壞將直接關(guān)系著車牌識(shí)別效果。通過(guò)前述步驟進(jìn)行車牌定位和圖像預(yù)處理后,下面就是二值化的字符分割環(huán)節(jié)。常見的字符分割方法有模板匹配、聚類分析[5]、投影分割等3種方法,在執(zhí)行分割之前先找到有效區(qū)域,并截取有效區(qū)域作為分割區(qū)域。在檢測(cè)有效區(qū)域時(shí)采用行列掃描的方法,先通過(guò)統(tǒng)計(jì)跳變次數(shù)找到上下邊界,再通過(guò)從左和從右逐列地掃描,認(rèn)為白色邊界最多的是起始列。
通過(guò)該方法將車牌中的字符單獨(dú)分割出來(lái),并且去除每個(gè)字符的上下方向上多余的邊框。因此得到的字符分割結(jié)果,字符應(yīng)該占滿整個(gè)分割圖像區(qū)域。為了便于后期的識(shí)別,因此將分割結(jié)果圖片統(tǒng)一縮放為 25*15 大小。
2.3 車牌字符識(shí)別
目前,車牌識(shí)別的技術(shù)相對(duì)來(lái)說(shuō)已趨于成熟,車牌識(shí)別的方法也較為多樣。一般情況下,利用傳統(tǒng)的模板匹配方法來(lái)進(jìn)行車牌識(shí)別,識(shí)別率已經(jīng)會(huì)達(dá)到較高水平,因而無(wú)需采用目前大火的深度學(xué)習(xí)的方法。
本次課程設(shè)計(jì)采用的就是較為經(jīng)典的模板匹配進(jìn)行車牌字符識(shí)別,將車牌字符的分割結(jié)果
I
I
I 分別與模板
I
′
I'
I′ 進(jìn)行對(duì)比,得出其差值
∣
I
?
I
′
∣
|I-I'|
∣I?I′∣,則所得差值最小的模板即為識(shí)別結(jié)果。需要額外說(shuō)明的一點(diǎn)是,由于 opencv-python 中自帶 cv2.matchTemplate()
函數(shù),因而在實(shí)際實(shí)現(xiàn)模板匹配過(guò)程中直接是調(diào)用該函數(shù)計(jì)算的。
2.4 實(shí)驗(yàn)圖像說(shuō)明
本次實(shí)驗(yàn)將使用到一張復(fù)雜場(chǎng)景下待車牌識(shí)別的圖像如 圖1 所示:
模板數(shù)據(jù)與我之前簡(jiǎn)單場(chǎng)景下車牌識(shí)別提供的數(shù)據(jù)相同,具體可參考:數(shù)字圖像處理—— 實(shí)驗(yàn)五 基于圖像分割的車牌定位識(shí)別_lan 606的博客-CSDN博客
具體的數(shù)據(jù)我已打包分享至如下百度網(wǎng)盤鏈接:5-carNumber_免費(fèi)高速下載|百度網(wǎng)盤-分享無(wú)限制 (baidu.com)
三、算法流程及實(shí)現(xiàn)
3.1 算法流程
整體的任務(wù)流程如報(bào)告第二章所述,現(xiàn)給出車牌識(shí)別任務(wù)的整體框架如 圖2 所示:
3.2 實(shí)現(xiàn)結(jié)果展示
通過(guò)rgb閾值初步篩選過(guò)后的二值化圖像(與給定閾值相近的賦值為255,其余像素點(diǎn)賦值為0):
在上述提取出來(lái)的二值化圖像基礎(chǔ)上,進(jìn)一步通過(guò)數(shù)學(xué)形態(tài)學(xué)操作(先膨脹后腐蝕),使得車牌區(qū)域連通為一整個(gè)塊:
最終提取出來(lái)的圖像(給車牌區(qū)域打上紅色方框):
初步提取出來(lái)的車牌:
對(duì)初步提取出來(lái)的車牌進(jìn)行角點(diǎn)校正,方便后續(xù)車牌識(shí)別過(guò)程:
對(duì)角點(diǎn)校正后的圖像進(jìn)行二值化:
通過(guò)車牌字符分割方法對(duì)車牌上幾個(gè)字符的分割結(jié)果:
最終的車牌識(shí)別結(jié)果:
-
注:關(guān)于識(shí)別結(jié)果的說(shuō)明
由于原始圖片上漢字 “川” 存在陰影,盡管在實(shí)驗(yàn)過(guò)程中通過(guò)灰度直方圖調(diào)整等方法進(jìn)行處理,但依舊無(wú)法正確識(shí)別。將分割出來(lái)的字符單獨(dú)拎出如 圖11 所示,可以看到存在缺失的漢字確實(shí)與閩相似。所以模板匹配的方法對(duì)原始輸入圖像的要求較高,想要獲得具有一定魯棒性的車牌識(shí)別算法,還是需要采用深度學(xué)習(xí)算法。文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-468203.html
文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-468203.html
圖11.?單獨(dú)的“川”字提取
3.3 實(shí)現(xiàn)代碼
# 數(shù)字圖像處理期末課程設(shè)計(jì)1:基于車道信息的違法車輛車牌識(shí)別
import cv2
import numpy as np
import matplotlib.pyplot as plt
# 展示圖片的函數(shù)
def pic_display(dis_name, dis_image):
cv2.imshow(dis_name, dis_image)
cv2.waitKey(0)
cv2.destroyAllWindows()
# 1.車牌定位
def license_region(image):
img_b = cv2.split(image)[0]
img_g = cv2.split(image)[1]
img_r = cv2.split(image)[2]
# 彩色信息特征初步定位:車牌定位并給resize后的圖像二值化賦值
standard_b = 138
standard_g = 63
standard_r = 23
standard_threshold = 50
img_test = image.copy()
for i in range(img_test.shape[0]):
for j in range(img_test.shape[1]):
# 提取與給定的r、g、b閾值相差不大的點(diǎn)(賦值為全白)
if abs(img_b[i, j] - standard_b) < standard_threshold \
and abs(img_g[i, j] - standard_g) < standard_threshold \
and abs(img_r[i, j] - standard_r) < standard_threshold:
img_test[i, j, :] = 255
# 其他所有的點(diǎn)賦值為全黑
else:
img_test[i, j, :] = 0
pic_display('img_binary', img_test)
# 基于數(shù)學(xué)形態(tài)學(xué)進(jìn)一步精細(xì)定位車牌區(qū)域
kernel = np.ones((3, 3), np.uint8)
img_resize_dilate = cv2.dilate(img_test, kernel, iterations=5) # 膨脹操作
img_resize_erosion = cv2.erode(img_resize_dilate, kernel, iterations=5) # 腐蝕操作
pic_display('img_resize_erosion', img_resize_erosion)
# cv2.cvtColor()函數(shù)將 三通道 的二值化圖像轉(zhuǎn)變?yōu)?單通道 的二值化圖像
img1 = cv2.cvtColor(img_resize_erosion, cv2.COLOR_BGR2GRAY)
contours = cv2.findContours(img1, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)[1]
# 通過(guò)區(qū)域面積,寬高比例的方式進(jìn)一步篩選車牌區(qū)域
MIN_AREA = 200 # 設(shè)定矩形的最小區(qū)域,用于去除無(wú)用的噪聲點(diǎn)
car_contours = []
for cnt in contours: # contours是長(zhǎng)度為18的一個(gè)tuple(元組)
# 框選 生成最小外接矩形 返回值(中心(x,y), (寬,高), 旋轉(zhuǎn)角度)rect[0]:矩形中心點(diǎn)坐標(biāo);rect[1]:矩形的高和寬;rect[2]:矩形的旋轉(zhuǎn)角度
rect = cv2.minAreaRect(cnt)
area_width, area_height = rect[1]
# 計(jì)算最小矩形的面積,初步篩選
area = rect[1][0] * rect[1][1] # 最小矩形面積
if area > MIN_AREA:
if area_width < area_height: # 選擇寬小于高的區(qū)域進(jìn)行寬和高的置換
area_width, area_height = area_height, area_width
# 求出寬高之比(要求矩形區(qū)域長(zhǎng)寬比在2到5.5之間,其他的排除)
wh_ratio = area_width / area_height
if 2 < wh_ratio < 5.5:
car_contours.append(rect)
box = cv2.boxPoints(rect) # 存放最小矩形的四個(gè)頂點(diǎn)坐標(biāo)(先列后行的順序)
box = np.int0(box) # 去除小數(shù)點(diǎn),只保留整數(shù)部分
region_out = box
return region_out
# 讀取需檢測(cè)的圖片
img = cv2.imdecode(np.fromfile(r'./data/Course_Design_1/1基于車道的違法車輛照片1.jpg', dtype=np.uint16), -1)
img = img[97:, :, :] # 去除原始圖片最上面的黑邊
# 原始圖片過(guò)大,壓縮為原始圖像尺寸的1/3,方便opencv-python出圖展示
img_resize = cv2.resize(img, None, fx=1 / 3, fy=1 / 3, interpolation=cv2.INTER_CUBIC)
# 對(duì)原始圖片進(jìn)行平滑和濾波處理
# 高斯平滑
img_resize_gaussian = cv2.GaussianBlur(img_resize, (5, 5), 1)
# 中值濾波
img_resize_median = cv2.medianBlur(img_resize_gaussian, 3)
# 定位車牌區(qū)域并繪圖展示
region = license_region(img_resize_median)
# 在原始圖像中用紅色方框標(biāo)注
img_showRect = img_resize.copy()
img_showRect = cv2.drawContours(img_showRect, [region], 0, (0, 0, 255), 2)
pic_display('img_showRect', img_showRect)
# 將車牌區(qū)域提取出來(lái)
region_real = region*3
car_region = img[np.min(region_real[:, 1]):np.max(region_real[:, 1])+5,
np.min(region_real[:, 0]):np.max(region_real[:, 0])+10, :]
pic_display('car_region', car_region)
# 2.對(duì)車牌區(qū)域進(jìn)行角點(diǎn)校正
# 原始車牌的四個(gè)角點(diǎn)(左下、左上、右下、右上,先列后行)
pts1 = np.float32([[7, 47], [9, 23], [100, 35], [102, 9]])
# 變換后分別在左下、左上、右下、右上四個(gè)點(diǎn)
pts2 = np.float32([[0, 50], [0, 0], [110, 50], [110, 0]]) # 對(duì)應(yīng)resize后的圖像尺寸大小
# 生成透視變換矩陣
M = cv2.getPerspectiveTransform(pts1, pts2)
# 進(jìn)行透視變換
dst = cv2.warpPerspective(car_region, M, (110, 50))
plt.subplot(121), plt.imshow(car_region[:, :, ::-1]), plt.title('input') # img[:, :, ::-1]是將BGR轉(zhuǎn)化為RGB
plt.subplot(122), plt.imshow(dst[:, :, ::-1]), plt.title('output')
plt.show()
# 3.車牌區(qū)域灰度化、二值化
car_region_gray = cv2.cvtColor(dst, cv2.COLOR_BGR2GRAY) # 將RGB圖像轉(zhuǎn)化為灰度圖像
# # otus二值化
# car_region_binary = cv2.threshold(car_region_gray, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)[1]
# 普通二值化方法
car_region_binary = cv2.threshold(car_region_gray, 87, 255, cv2.THRESH_BINARY)[1]
pic_display('car_region_binary', car_region_binary)
# 4.車牌分割(均分割為25*15的圖片)height=25,width=15
# 模板分割函數(shù),只針對(duì)單個(gè)字符,用于去除其周圍的邊緣,并resize
def template_segmentation(origin_img):
# 提取字符各列滿足條件(有兩個(gè)255的單元格)的索引
col_index = []
for col in range(origin_img.shape[1]): # 對(duì)于圖像的所有列
if np.sum(origin_img[:, col]) >= 2*255:
col_index.append(col)
col_index = np.array(col_index)
# 提取字符各行滿足條件(有兩個(gè)255的單元格)的索引
row_index = []
for row in range(origin_img.shape[0]):
if np.sum(origin_img[row, :]) >= 2*255:
row_index.append(row)
row_index = np.array(row_index)
# 按索引提取字符(符合條件的行列中取min-max),并resize到25*15大小
output_img = origin_img[np.min(row_index):np.max(row_index)+1, np.min(col_index):np.max(col_index)+1]
output_img = np.uint8(output_img)
if col_index.shape[0] <= 3 or row_index.shape[0] <= 3:
output_img = origin_img[np.min(row_index):np.max(row_index)+1, np.min(col_index):np.max(col_index)+1]
pad_row1 = np.int8(np.floor((25 - output_img.shape[0]) / 2))
pad_row2 = np.int8(np.ceil((25 - output_img.shape[0]) / 2))
pad_col1 = np.int8(np.floor((15 - output_img.shape[1]) / 2))
pad_col2 = np.int8(np.ceil((15 - output_img.shape[1]) / 2))
output_img = np.pad(output_img, ((pad_row1, pad_row2), (pad_col1, pad_col2)), 'constant',
constant_values=(0, 0))
output_img = np.uint8(output_img)
else:
output_img = cv2.resize(output_img, (15, 25), interpolation=0)
return output_img
# 對(duì)原始車牌摳圖,摳出每一個(gè)字符
temp_col_index = []
car_region_binary[47:50, :] = 0
car_region_binary[:, 0:4] = 0
car_region_binary[:, -1] = 0
for col in range(car_region_binary.shape[1]):
if np.sum(car_region_binary[:, col]) > 5*255: # 提取大于5個(gè)255的列
temp_col_index.append(col)
temp_col_index = np.array(temp_col_index)
flag = 0 # 值是7個(gè)字符的起始列
flag_i = 0 # 值的變化范圍:從0到6(對(duì)應(yīng)車牌的7個(gè)字符)
car_license_out_col = np.uint8(np.zeros([7, 30])) # 7行的數(shù)組存儲(chǔ)車牌上的7個(gè)需識(shí)別的字
for j in range(temp_col_index.shape[0]-1):
# 提取的>=3個(gè)255的列之間不是相鄰的且至少有8長(zhǎng)度的字符
if temp_col_index[j+1]-temp_col_index[j] >= 3 and (temp_col_index[j+1]-temp_col_index[flag]) >= 8:
temp = temp_col_index[flag:j+1]
temp = np.append(temp, np.zeros(30-temp.shape[0])) # 補(bǔ)成30維的向量,方便最后賦值給car_license_out_col
temp = np.uint8(temp.reshape(1, 30))
car_license_out_col[flag_i, :] = temp
flag = j+1
flag_i = flag_i+1
temp = temp_col_index[flag:]
temp = np.append(temp, np.zeros(30-temp.shape[0]))
temp = np.uint8(temp.reshape(1, 30))
car_license_out_col[flag_i, :] = temp
# 分別提取7個(gè)字符(通過(guò)行進(jìn)行篩選)
car_license_out_row = np.uint8(np.zeros([7, 30]))
for row in range(car_license_out_row.shape[0]): # 對(duì)應(yīng)車牌上的7個(gè)字符
temp = car_license_out_col[row, :]
index = 0
for i in range(temp.shape[0]): # 去除列索引中多余的0
if temp[i] == 0:
index = i
break
col_temp = temp[0:index]
temp_img = car_region_binary[:, np.min(col_temp):np.max(col_temp)+1]
t = np.nonzero(np.sum(temp_img, axis=1))
if row == 0:
province1 = temp_img[t, :] # 漢字后續(xù)擴(kuò)展成40*40
province1 = province1[0, :, :]
province1 = template_segmentation(province1)
province1 = np.uint8(province1)
if row == 1:
province2 = temp_img[t, :] # 字母和數(shù)字后續(xù)擴(kuò)展成40*40
province2 = province2[0, :, :]
province2 = template_segmentation(province2)
province2 = np.uint8(province2)
if row == 2:
car_number1 = temp_img[t, :]
car_number1 = car_number1[0, :, :]
car_number1 = template_segmentation(car_number1)
car_number1 = np.uint8(car_number1)
if row == 3:
car_number2 = temp_img[t, :]
car_number2 = car_number2[0, :, :]
car_number2 = template_segmentation(car_number2)
car_number2 = np.uint8(car_number2)
if row == 4:
car_number3 = temp_img[t, :]
car_number3 = car_number3[0, :, :]
car_number3 = template_segmentation(car_number3)
car_number3 = np.uint8(car_number3)
if row == 5:
car_number4 = temp_img[t, :]
car_number4 = car_number4[0, :, :]
car_number4 = template_segmentation(car_number4)
car_number4 = np.uint8(car_number4)
if row == 6:
car_number5 = temp_img[t, :]
car_number5 = car_number5[0, :, :]
car_number5 = template_segmentation(car_number5)
car_number5 = np.uint8(car_number5)
cv2.imshow('province1', province1)
cv2.imshow('province2', province2)
cv2.imshow('car_number1', car_number1)
cv2.imshow('car_number2', car_number2)
cv2.imshow('car_number3', car_number3)
cv2.imshow('car_number4', car_number4)
cv2.imshow('car_number5', car_number5)
cv2.waitKey(0)
cv2.destroyAllWindows()
# 5.車牌識(shí)別
# 讀取所有的字母字符列表及其模板
Alphabet_character = open(r'./data/5-carNumber./英文.txt', encoding="gbk").read()
Alphabet_character = Alphabet_character.split("\n")
Alphabet_char_template = np.load(r'./data/5-carNumber/Alphabet_char_template.npy')
# 讀取所有的漢字字符列表及其模板
Chinese_character = open(r'./data/5-carNumber./漢字.txt', encoding="gbk").read()
Chinese_character = Chinese_character.split("\n")
Chinese_char_template = np.load(r'./data/5-carNumber/Chinese_char_template.npy')
# 讀取所有的數(shù)字字符列表及其模板
Number_character = open(r'./data/5-carNumber./數(shù)字.txt', encoding="gbk").read()
Number_character = Number_character.split("\n")
Number_char_template = np.load(r'./data/5-carNumber/Number_char_template.npy')
# 進(jìn)行字符識(shí)別
car_character = np.uint8(np.zeros([7, 25, 15]))
car_character[0, :, :] = province1.copy()
car_character[1, :, :] = province2.copy()
car_character[2, :, :] = car_number1.copy()
car_character[3, :, :] = car_number2.copy()
car_character[4, :, :] = car_number3.copy()
car_character[5, :, :] = car_number4.copy()
car_character[6, :, :] = car_number5.copy()
match_length = Chinese_char_template.shape[0]+Alphabet_char_template.shape[0]+Number_char_template.shape[0]
match_mark = np.zeros([7, match_length])
Chinese_char_start = 0
Chinese_char_end = Chinese_char_template.shape[0]
Alphabet_char_start = Chinese_char_template.shape[0]
Alphabet_char_end = Chinese_char_template.shape[0]+Alphabet_char_template.shape[0]
Number_char_start = Chinese_char_template.shape[0]+Alphabet_char_template.shape[0]
Number_char_end = match_length
for i in range(match_mark.shape[0]): # 7個(gè)需識(shí)別的字符
for j in range(Chinese_char_start, Chinese_char_end): # 所有的漢字模板
match_mark[i, j] = cv2.matchTemplate(car_character[i, :, :], Chinese_char_template[j, :, :], cv2.TM_CCOEFF)
# 所有的字母模板
for j in range(Alphabet_char_start, Alphabet_char_end):
match_mark[i, j] = cv2.matchTemplate(car_character[i, :, :],
Alphabet_char_template[j-Alphabet_char_start, :, :],
cv2.TM_CCOEFF)
# 所有的數(shù)字模板
for j in range(Number_char_start, Number_char_end):
match_mark[i, j] = cv2.matchTemplate(car_character[i, :, :],
Number_char_template[j-Number_char_start, :, :],
cv2.TM_CCOEFF)
output_index = np.argmax(match_mark, axis=1)
output_char = []
for i in range(output_index.shape[0]):
if 0 <= output_index[i] <= 28:
output_char.append(Chinese_character[output_index[i]])
if 29 <= output_index[i] <= 54:
output_char.append(Alphabet_character[output_index[i]-29])
if 55 <= output_index[i] <= 64:
output_char.append(Number_character[output_index[i]-55])
# 打印識(shí)別結(jié)果
for i in range(len(output_char)):
if i == 0:
print('province1:' + output_char[0])
if i == 1:
print('province2:' + output_char[1])
if i == 2:
print('car1:' + output_char[2])
if i == 3:
print('car2:' + output_char[3])
if i == 4:
print('car3:' + output_char[4])
if i == 5:
print('car4:' + output_char[5])
if i == 6:
print('car5:' + output_char[6])
參考文獻(xiàn)
[1] 李強(qiáng), 張娟. 一種改進(jìn)的基于模板匹配的污損車牌識(shí)別方法[J]. 智能計(jì)算機(jī)與應(yīng)用, 2019, 9(03): 113-117. [2] 駱雪超, 劉桂雄, 馮云慶, 等. 一種基于車牌特征信息的車牌識(shí)別方法[J]. 華南理工大學(xué)學(xué)報(bào)(自然科學(xué)版), 2003, (04): 70-73. [3] 趙志剛, 繆凱, 呂慧顯. 基于RBFNN和非全字符輸入的車牌識(shí)別方法[J]. 光電子.激光, 2007, (12): 1457-1461. [4] 劉尚旺, 段德全, 崔艷萌, 等. 二次定位車牌分割及識(shí)別方法[J]. 河南師范大學(xué)學(xué)報(bào)(自然科學(xué)版), 2016, 44(04): 151-156. [5] 吳益紅, 許鋼, 江娟娟, 等. 一種用于工件識(shí)別的LBP-HOG特征融合方法[J]. 南陽(yáng)師范學(xué)院學(xué)報(bào), 2016, 15(09): 33-38.到了這里,關(guān)于數(shù)字圖像處理——大作業(yè) 基于車道信息的違法車輛車牌識(shí)別的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!