別全流程:預(yù)處理、分割與模板匹配實(shí)戰(zhàn)解析)
簡(jiǎn)介基于Matlab的車牌識(shí)別課程設(shè)計(jì)報(bào)告以docx文檔形式提供內(nèi)容覆蓋車牌識(shí)別系統(tǒng)的完整設(shè)計(jì)流程從系統(tǒng)組成、車輛檢測(cè)與圖像采集到車牌定位、字符分割與字符識(shí)別算法并配有詳細(xì)設(shè)計(jì)步驟、流程圖和Matlab源代碼片段適合信息科學(xué)與工程專業(yè)學(xué)生完成課程設(shè)計(jì)或進(jìn)行圖像處理、模式識(shí)別實(shí)踐。報(bào)告重點(diǎn)闡述了垂直投影法字符分割、模板匹配與神經(jīng)網(wǎng)絡(luò)識(shí)別等核心方法同時(shí)包含開(kāi)運(yùn)算背景分離、二值化等預(yù)處理實(shí)現(xiàn)可幫助讀者理解車牌識(shí)別從圖像輸入到號(hào)碼輸出的完整鏈路。資源共1個(gè)docx文件壓縮包大小約1.37MB屬于輕量級(jí)文檔型資料已有116人學(xué)習(xí)下載在同主題課程設(shè)計(jì)報(bào)告中有一定參考價(jià)值。讀者可用于對(duì)照自己的設(shè)計(jì)方案、補(bǔ)充算法原理說(shuō)明也可借鑒其中的Matlab代碼快速搭建車牌識(shí)別原型系統(tǒng)。1. 這份Matlab車牌識(shí)別課程設(shè)計(jì)定位、分割、識(shí)別一條龍車牌識(shí)別是圖像處理課設(shè)里的常青樹(shù)很多學(xué)生第一次接觸“圖像處理到底怎么落地”就是從這個(gè)題目開(kāi)始的。這套Matlab車牌識(shí)別課程設(shè)計(jì)報(bào)告從一張普通照片出發(fā)把灰度化、背景相減、二值化、Canny邊緣檢測(cè)、形態(tài)學(xué)開(kāi)閉運(yùn)算、區(qū)域?qū)捀弑群Y選、傾斜校正、投影分割、模板匹配這些環(huán)節(jié)完整走了一遍報(bào)告文檔和源代碼都是齊的。它的價(jià)值不在于識(shí)別率有多高而在于把“定位-分割-識(shí)別”這條鏈路講得可以一步步復(fù)現(xiàn)。適合兩類人一是剛拿到課設(shè)題目、想快速跑通全流程的學(xué)生二是工作中需要處理圖像定位和字符分割、想借一套現(xiàn)成思路的從業(yè)者。下面我把這條鏈路拆開(kāi)講重點(diǎn)落在參數(shù)怎么設(shè)、哪幾步容易翻車。2. 圖像預(yù)處理與二值化灰度化、背景相減和閾值公式拆解報(bào)告從imread(3.jpg)讀入圖像開(kāi)始但真正決定后續(xù)成敗的是預(yù)處理階段三個(gè)操作灰度化、開(kāi)運(yùn)算背景估計(jì)、減法增強(qiáng)。這三個(gè)操作合起來(lái)做了一件事把一張光照復(fù)雜、背景雜亂的照片變成“亮字符、暗背景”的理想二值圖。2.1 灰度化與背景估計(jì)為什么要先做一次開(kāi)運(yùn)算彩色圖像三通道信息量大直接處理會(huì)拖慢速度更重要的是車牌識(shí)別本身依賴的是亮度和形狀特征而不是顏色。rgb2gray是Matlab標(biāo)準(zhǔn)灰度化接口內(nèi)部按亮度加權(quán)公式0.299R 0.587G 0.114B對(duì)三通道加權(quán)求和。這一步?jīng)]有玄學(xué)就是降維提速。Scolor imread(3.jpg); % 讀入彩色原圖 Sgray rgb2gray(Scolor); % RGB轉(zhuǎn)灰度后續(xù)所有處理都在單通道上進(jìn)行 figure, imshow(Sgray), title(原始黑白圖像); s strel(disk, 13); % 圓盤(pán)結(jié)構(gòu)元素半徑13 Bgray imopen(Sgray, s); % 開(kāi)運(yùn)算估計(jì)背景亮度 figure, imshow(Bgray), title(背景圖像);imopen是形態(tài)學(xué)開(kāi)運(yùn)算先腐蝕后膨脹。腐蝕把細(xì)小的亮目標(biāo)抹掉膨脹再把大尺度的背景結(jié)構(gòu)恢復(fù)回來(lái)。disk半徑13的意思是直徑26像素以下的亮細(xì)節(jié)會(huì)被腐蝕掉只留下緩慢變化的背景亮度場(chǎng)。這個(gè)13是經(jīng)驗(yàn)值和圖像分辨率強(qiáng)相關(guān)。如果原圖是千萬(wàn)像素級(jí)別的大圖13可能偏小背景里會(huì)殘留車體輪廓如果是三四百像素的小圖13可能偏大連車牌底板都被“背景化”了。Egray imsubtract(Sgray, Bgray); % 原圖減背景突出比背景亮的目標(biāo) figure, imshow(Egray), title(增強(qiáng)黑白圖像);imsubtract把原圖灰度值和背景估計(jì)值逐像素相減。實(shí)際效果是車身、路面這類緩變區(qū)域被壓暗而白色車牌字符、車牌底板邊緣這類比局部背景亮的目標(biāo)被保留下來(lái)。報(bào)告把這步叫“圖像增強(qiáng)”本質(zhì)是高通濾波的形態(tài)學(xué)版本。2.2 背景相減與閾值二值化level 那行代碼的來(lái)歷增強(qiáng)之后就要二值化。報(bào)告里這段代碼是很多人看不懂的地方fmax1 double(max(max(Egray))); % 增強(qiáng)圖的最大灰度值 fmin1 double(min(min(Egray))); % 增強(qiáng)圖的最小灰度值 level (fmax1 - (fmax1 - fmin1)/3) / 255; % 閾值落在動(dòng)態(tài)范圍高端1/3處 bw22 im2bw(Egray, level); % 大于level置1小于level置0 bw2 double(bw22); % 轉(zhuǎn)成double方便后續(xù)計(jì)算 figure, imshow(bw2), title(圖像二值化);把 level 的公式展開(kāi)level (max - (max-min)/3) / 255也就是(min 2*(max-min)/3) / 255。意思是閾值取在灰度動(dòng)態(tài)范圍從低到高的 2/3 處換句話說(shuō)只保留灰度最高的那 1/3 區(qū)域。為什么這么設(shè)因?yàn)樵谠鰪?qiáng)圖里車牌字符是整幅圖最亮的目標(biāo)取高端閾值能最大限度把字符和亮噪點(diǎn)分開(kāi)。除以 255 是因?yàn)閕m2bw的 level 參數(shù)必須是 [0,1] 區(qū)間的歸一化值。這個(gè)公式是典型的工程經(jīng)驗(yàn)值不是統(tǒng)計(jì)意義上的最優(yōu)閾值。它隱含一個(gè)假設(shè)字符比背景亮而且亮得足夠多。光照條件一變這個(gè)閾值就會(huì)飄。比如強(qiáng)逆光下車身反光max 被高光點(diǎn)拉高閾值跟著升高真字符可能被誤殺陰天整體灰度偏低動(dòng)態(tài)范圍被壓縮閾值可能過(guò)低路面紋理全變成前景。所以復(fù)現(xiàn)時(shí)第一件事是打印fmax1、fmin1和level三個(gè)值看二值圖里車牌字符是不是完整白色。2.3 Canny 邊緣檢測(cè)與形態(tài)學(xué)濾波讓車牌區(qū)域連成塊二值圖里字符是實(shí)心的白色塊直接做區(qū)域標(biāo)記會(huì)出現(xiàn)一個(gè)字符被算成多個(gè)連通域的情況。報(bào)告的處理是先對(duì)二值圖做邊緣檢測(cè)把實(shí)心塊變成輪廓再用形態(tài)學(xué)操作把輪廓重新焊接成車牌形狀。grd edge(bw2, canny); % Canny邊緣檢測(cè)提取二值圖輪廓 figure, imshow(grd), title(圖像邊緣提取); bg1 imclose(grd, strel(rectangle,[5,19])); % 閉運(yùn)算焊接口字?jǐn)嗔?figure, imshow(bg1), title(圖像閉運(yùn)算[5,19]); bg3 imopen(bg1, strel(rectangle,[5,19])); % 開(kāi)運(yùn)算去掉小噪點(diǎn) figure, imshow(bg3), title(圖像開(kāi)運(yùn)算[5,19]); bg2 imopen(bg3, strel(rectangle,[19,1])); % 豎直細(xì)長(zhǎng)條開(kāi)運(yùn)算按高度篩 figure, imshow(bg2), title(圖像開(kāi)運(yùn)算[19,1]);這里三個(gè)結(jié)構(gòu)元素各有分工。第一個(gè)是[5,19]矩形寬19高5橫向長(zhǎng)縱向短。閉運(yùn)算先把字符輪廓內(nèi)部斷裂和字符間的小缺口焊起來(lái)形成橫向條帶接著同樣的矩形做開(kāi)運(yùn)算把比這個(gè)尺寸小的孤立噪點(diǎn)清掉。第三個(gè)[19,1]是寬1高19的豎直細(xì)長(zhǎng)條開(kāi)運(yùn)算要求圖中結(jié)構(gòu)能完整容納一個(gè)19像素高的豎條才保留于是細(xì)橫線、短劃痕這類噪聲被剔除而車牌字符行因?yàn)楦叨冉咏?9像素被保留。這組5和19的數(shù)字不是隨便拍的它們對(duì)應(yīng)的是“字符在小分辨率圖像里的線寬量級(jí)”。如果你的圖像采集距離遠(yuǎn)、車牌在畫(huà)面里占比小19這個(gè)數(shù)可能要縮到12甚至8如果車牌占據(jù)畫(huà)面很大19會(huì)不夠用字符行會(huì)被誤刪。改參數(shù)的標(biāo)準(zhǔn)只有一個(gè)讓處理后只剩車牌區(qū)域這個(gè)連通塊車身其他紋理全部消失。3. 車牌候選區(qū)域篩選區(qū)域標(biāo)記、寬高比與先驗(yàn)知識(shí)形態(tài)學(xué)做完圖像里剩下的白色連通塊通常不止車牌一個(gè)——車燈、保險(xiǎn)杠上的反光條、車身文字都可能殘留。這一步要把真正的車牌區(qū)域從這些候選塊里挑出來(lái)靠的是兩個(gè)先驗(yàn)連通域面積和寬高比。3.1 bwlabel 與區(qū)域特征統(tǒng)計(jì)老接口 imfeature 的替代方案報(bào)告里用的是bwlabel加imfeature前者標(biāo)記連通域后者計(jì)算區(qū)域特征。問(wèn)題是imfeature在Matlab新版本里已經(jīng)被移除了直接跑會(huì)報(bào)“未定義函數(shù)”。必須換成regionprops字段名和返回結(jié)構(gòu)基本一致。[L, num] bwlabel(bg2, 8); % 8連通標(biāo)記num是連通域個(gè)數(shù) RGB label2rgb(L, spring, k, shuffle); % 偽彩色顯示每個(gè)連通域 figure, imshow(RGB), title(圖像彩色標(biāo)記); stats regionprops(L, Area, BoundingBox); Area [stats.Area]; % 每個(gè)區(qū)域的像素面積 BoundingBox reshape([stats.BoundingBox], 4, num); % 每行[x y width height]bwlabel的8表示8鄰域連通即上下左右加四個(gè)對(duì)角方向都算連通。對(duì)車牌字符和邊框來(lái)說(shuō)8連通容易把斷開(kāi)的筆畫(huà)重新接上適合后續(xù)整體提取。regionprops返回的BoundingBox格式是[x, y, width, height]x和y是區(qū)域最小外接矩形的左上角坐標(biāo)width和height是寬和高單位是像素。label2rgb是純可視化輔助把每個(gè)連通域染成不同顏色方便肉眼確認(rèn)“到底哪些塊被標(biāo)記出來(lái)了”。這一步對(duì)調(diào)試非常有用尤其當(dāng)篩選結(jié)果不對(duì)時(shí)先看彩色標(biāo)記圖能立刻判斷是形態(tài)學(xué)參數(shù)的問(wèn)題還是篩選閾值的問(wèn)題。3.2 寬高比篩選把 3.14:1 用進(jìn) BoundingBox車牌篩選最核心的規(guī)則是寬高比。我國(guó)藍(lán)底白字車牌標(biāo)準(zhǔn)尺寸是440mm×140mm寬高比約3.14:1。加上車牌邊框、鉚釘和字符區(qū)域的實(shí)際邊界二值化后提取的候選塊寬高比通常會(huì)落在2.5到4.5之間。報(bào)告里這部分只畫(huà)了流程圖沒(méi)有給出具體閾值實(shí)際操作時(shí)我一般用下面這組條件candidates []; for k 1:num w BoundingBox(k,3); h BoundingBox(k,4); ratio w / h; % 車牌寬高比約3.14放寬到2.5~4.5面積下限防小噪點(diǎn) if ratio 2.5 ratio 4.5 Area(k) 500 candidates [candidates; k, BoundingBox(k,:)]; end end注意Area的單位是像素個(gè)數(shù)不是物理面積所以下限500這個(gè)值完全取決于圖像分辨率。更穩(wěn)的做法是先把所有連通域的Area打印出來(lái)看車牌區(qū)域和其他噪點(diǎn)的面積分布取一個(gè)能明顯分開(kāi)兩者的值。寬高比的上下限同樣要結(jié)合圖片里的車牌傾斜程度如果車牌傾斜超過(guò)10度外接矩形的寬高比會(huì)被拉大上限4.5可能不夠建議打印所有候選塊的寬高比再定閾值。篩選邏輯還有一個(gè)隱藏點(diǎn)如果二值化做得不好車牌字符和底板沒(méi)有被形態(tài)學(xué)焊成一個(gè)連通塊而是碎成幾塊那么每一塊的寬高比都不可能是3.14。這種時(shí)候不要急著調(diào)篩選參數(shù)回頭查第2章的形態(tài)學(xué)結(jié)構(gòu)元素尺寸。3.3 灰度子圖與二值子圖為投影分析準(zhǔn)備的輸入找到候選區(qū)域后要用BoundingBox從原灰度圖和二值圖中分別裁剪出子圖。報(bào)告里灰度子圖叫subcol二值子圖叫sbw1后面所有投影和分割都在二值子圖上進(jìn)行。% 假設(shè)篩選出的最佳候選區(qū)為box [x y w h] box candidates(1, 2:5); % 取第一個(gè)候選區(qū)實(shí)際應(yīng)比較所有候選 subcol imcrop(Sgray, box); % 從灰度圖裁出車牌區(qū)域 sbw1 imcrop(bw2, box); % 從二值圖裁出對(duì)應(yīng)區(qū)域 figure, subplot(1,2,1), imshow(subcol), title(灰度子圖); subplot(1,2,2), imshow(sbw1), title(二值子圖);這里有個(gè)容易被忽略的細(xì)節(jié)裁剪必須用同一個(gè)box同時(shí)作用于灰度圖和二值圖保證兩個(gè)子圖嚴(yán)格對(duì)齊?;叶茸訄D是給人看的用來(lái)確認(rèn)“這確實(shí)是車牌”二值子圖是給后續(xù)算法用的投影、擬合、分割全部基于它。如果二值子圖里字符連成一條黑帶或者碎成麻點(diǎn)不要繼續(xù)往下走先回頭調(diào)整二值化閾值。到這一步圖像已經(jīng)從“一張照片”變成了“一塊像車牌的二值區(qū)域”。接下來(lái)最考驗(yàn)代碼功力的是投影分析和傾斜校正這也是報(bào)告里代碼最亂、變量最容易對(duì)不上的部分。4. 傾斜校正與字符分割投影峰谷分析的完整鏈路投影分析的核心思想很樸素把二值圖像按行或按列累加白點(diǎn)數(shù)量字符區(qū)域會(huì)在投影曲線上形成峰字符間隙形成谷。問(wèn)題是報(bào)告里markrow、markcol這一堆變量的賦值過(guò)程被省略了直接照跑必然報(bào)錯(cuò)。下面這套是我按相同邏輯重寫(xiě)的等價(jià)實(shí)現(xiàn)能直接跑通。4.1 水平投影與峰谷分析markrow 系列的現(xiàn)代寫(xiě)法% sbw1為第3章得到的車牌二值子圖 histrow sum(sbw1, 2); % 水平投影每一行白點(diǎn)數(shù)量求和 figure, bar(histrow), title(水平投影含邊框); % 投影序列轉(zhuǎn)0/1超過(guò)峰值20%的行算字符行 projMask histrow max(histrow) * 0.2; d diff([0; projMask; 0]); % 前后差分找跳變沿 rowTop find(d 1); % 上升沿字符帶起始行 rowBot find(d -1) - 1; % 下降沿字符帶結(jié)束行sum(sbw1, 2)對(duì)每行求和得到的是行號(hào)到白點(diǎn)數(shù)的映射。一個(gè)標(biāo)準(zhǔn)車牌的投影曲線從上到下應(yīng)該是上邊框峰、字符峰群、下邊框峰。max(histrow)*0.2這個(gè)閾值把投影曲線壓成0/1序列再用diff找前后狀態(tài)變化的位置——從0變1是行帶開(kāi)始從1變0是行帶結(jié)束。rowTop和rowBot就是報(bào)告里markrow和markrow1想表達(dá)的東西。如果這段代碼跑出來(lái)rowTop和rowBot長(zhǎng)度一大串說(shuō)明二值圖里殘留的噪聲行太多往下走之前先把第2章的形態(tài)學(xué)參數(shù)重新過(guò)一遍。4.2 車牌旋轉(zhuǎn)校正poly1 擬合、弧度轉(zhuǎn)角度與 imrotate水平投影曲線如果峰谷不明顯比如字符行整片糊成一個(gè)寬峰最常見(jiàn)的原因是車牌傾斜。傾斜車牌在水平投影上各字符行錯(cuò)位疊加峰被抹平。報(bào)告的解法是線性擬合車牌邊緣算出傾角再把圖像轉(zhuǎn)回來(lái)。% 逐行找第一個(gè)白點(diǎn)坐標(biāo)擬合車牌上邊緣直線 xdata zeros(size(sbw1,1),1); ydata (1:size(sbw1,1)); for r 1:size(sbw1,1) c find(sbw1(r,:) 1); if ~isempty(c) xdata(r) c(1); % 該行第一個(gè)白點(diǎn)的列號(hào) end end valid xdata 0; % 剔除全黑行 fresult fit(xdata(valid), ydata(valid), poly1); % 一階多項(xiàng)式擬合 angle atan(fresult.p1) * 180 / pi; % 斜率轉(zhuǎn)角度弧度換度 sbw imrotate(sbw1, angle, bilinear, crop); % 旋轉(zhuǎn)校正 figure, imshow(sbw), title([車牌旋轉(zhuǎn)角: , num2str(angle), 度]);fit是曲線擬合工具箱的函數(shù)poly1表示擬合y p1*x p2這種一次直線p1就是斜率也就是tan(theta)。atan(p1)得到弧度乘以180/pi轉(zhuǎn)成角度。imrotate三參數(shù)分別是旋轉(zhuǎn)角度、插值方式、是否裁剪。bilinear雙線性插值比默認(rèn)最近鄰更能避免邊緣鋸齒crop讓輸出圖像和原圖同尺寸。這里有兩個(gè)坑。第一fit要求輸入是列向量xdata和ydata維度必須一致所以要先剔除全黑行。第二擬合出來(lái)的角度正負(fù)取決于車牌往哪邊歪不要手動(dòng)把角度改成絕對(duì)值直接交給imrotate就行它會(huì)按反方向轉(zhuǎn)正。4.3 去邊框與垂直投影字符中心、字符寬度怎么算旋轉(zhuǎn)校正后重新做水平投影這次的目標(biāo)是精確去掉上下邊框拿到純字符帶。histrow2 sum(sbw, 2); projMask2 histrow2 max(histrow2) * 0.2; d2 diff([0; projMask2; 0]); rowtop find(d2 1); rowbot find(d2 -1) - 1; maxhight max(rowbot - rowtop 1); % 字符行高度 % 取最寬的字符帶來(lái)裁剪 [~, idx] max(rowbot - rowtop 1); sbw2 sbw(rowtop(idx):rowbot(idx), :); % 去掉上下邊框的字符帶 histcol sum(sbw2, 1); % 垂直投影每列白點(diǎn)數(shù)量 figure, bar(histcol), title(垂直投影去水平邊框后);垂直投影的目標(biāo)是找到每個(gè)字符的左右邊界。字符列白點(diǎn)多形成峰字符間隙形成谷。同樣用跳變檢測(cè)projCol histcol max(histcol) * 0.15; dCol diff([0, projCol, 0]); colTop find(dCol 1); % 每個(gè)字符帶的起始列 colBot find(dCol -1) - 1; % 每個(gè)字符帶的結(jié)束列 width colBot - colTop 1; center colTop width / 2; % 字符中心位置 gap diff(center); % 相鄰字符中心距離 [~, maxGapIdx] max(gap); % 最大間距通常出現(xiàn)在第一個(gè)字符之后max(gap)找的是相鄰字符中心距離最大的位置。因?yàn)檐嚺频谝粋€(gè)字符是漢字寬度通常比后續(xù)字母數(shù)字窄它和第二個(gè)字符之間的中心距會(huì)被拉大。報(bào)告里for k findmax-1:findmax5就是這個(gè)邏輯從最大間距的前一個(gè)字符開(kāi)始連續(xù)取7個(gè)正好覆蓋整個(gè)車牌的7個(gè)字符位。如果你的圖片里漢字本身很寬或者有間隔符干擾這個(gè)假設(shè)會(huì)失效到時(shí)候打印center和gap人工核對(duì)。4.4 切字符并歸一化22×14 標(biāo)準(zhǔn)子圖的由來(lái)拿到每個(gè)字符中心和最大字符寬度后就可以切割了maxwidth max(width); % 最大字符寬度 l 1; for k (maxGapIdx - 1) : (maxGapIdx 5) cleft center(k) - maxwidth / 2; % 切割左邊界 cright center(k) maxwidth / 2 - 2; % 右邊界減2是避免重疊 cleft max(cleft, 1); cright min(cright, size(sbw2, 2)); SegBw1 sbw2(:, cleft:cright); % 原始尺寸字符塊 SegBw2 imresize(SegBw1, [22 14]); % 歸一化為22行14列標(biāo)準(zhǔn)子圖 figure, imshow(SegBw2); l l 1; endmaxwidth是垂直投影里最寬字符的寬度用它作為切割窗口的參考寬度能保證每個(gè)字符都被完整框住。cleft和cright用字符中心加減半個(gè)最大寬度得到最后用max、min把邊界限制在圖像范圍內(nèi)防止越界。22×14 是報(bào)告定的標(biāo)準(zhǔn)子圖尺寸22對(duì)應(yīng)字符高度14對(duì)應(yīng)字符寬度。不同圖像里車牌大小差異很大直接拿原始尺寸去匹配模板沒(méi)有任何意義必須統(tǒng)一縮放。imresize默認(rèn)最近鄰插值在縮放比例不是整數(shù)時(shí)容易產(chǎn)生鋸齒建議改成imresize(SegBw1, [22 14], bilinear)。5. 字符識(shí)別模板匹配、神經(jīng)網(wǎng)絡(luò)與失敗案例復(fù)盤(pán)字符分割完成最后一步是識(shí)別。報(bào)告同時(shí)提到了模板匹配和BP神經(jīng)網(wǎng)絡(luò)兩條路線并給出了一個(gè)完整失敗案例。這一章把兩條路線的原理和取舍講清楚。5.1 模板匹配流程與樣本庫(kù)組織模板匹配的思路是準(zhǔn)備一個(gè)樣本庫(kù)每個(gè)樣本是已知字符的22×14二值圖然后把待識(shí)別字符和庫(kù)中所有樣本逐像素比較誤差最小的就是結(jié)果。報(bào)告里的實(shí)現(xiàn)是“樣本與數(shù)據(jù)庫(kù)中的圖片相減找誤差最小的圖片”對(duì)應(yīng)代碼如下function ch matchChar(cutImg, sampleDir) cutImg imresize(cutImg, [22 14]); % 統(tǒng)一尺寸 cutImg im2double(cutImg); files dir(fullfile(sampleDir, *.jpg)); bestErr inf; ch ; for i 1:length(files) t imread(fullfile(sampleDir, files(i).name)); t imresize(t, [22 14]); t im2double(t); err sum(sum(abs(cutImg - t))); % 絕對(duì)差求和SAD誤差 if err bestErr bestErr err; ch files(i).name(1); % 樣本文件名首字符即類別 end end end誤差度量用絕對(duì)差求和SAD還是平方差求和SSD都可以SSD對(duì)差異更敏感匹配結(jié)果更尖銳但受離群像素影響更大。樣本庫(kù)文件名直接編碼字符類別比如首字符是“0”的樣本就命名為0_1.jpg、0_2.jpg匹配結(jié)束后取文件名首字符作為識(shí)別結(jié)果。報(bào)告的imwrite里用了F:\MATLAB\work\sam\image這種絕對(duì)路徑復(fù)現(xiàn)時(shí)建議改成相對(duì)路徑加fullfile否則換電腦必崩。模板匹配最怕兩件事樣本量不足和樣本與待識(shí)別字符風(fēng)格不一致。同一個(gè)字符不同字體、不同筆畫(huà)粗細(xì)、不同車牌材質(zhì)反光在22×14的歸一化圖像上可能差出幾百個(gè)像素的SAD誤差。樣板庫(kù)每個(gè)字符最好放10張以上從不同車牌上切下來(lái)的真實(shí)樣本。5.2 神經(jīng)網(wǎng)絡(luò)替代方案四個(gè)子網(wǎng)分開(kāi)訓(xùn)練報(bào)告提到兩種神經(jīng)網(wǎng)絡(luò)做法一種是先提取特征再訓(xùn)練分類器另一種是直接把圖像像素送入網(wǎng)絡(luò)讓網(wǎng)絡(luò)自己學(xué)特征。報(bào)告中用的是后者更適用的方案字符圖像直接拉成向量輸入BP網(wǎng)絡(luò)。% 示意把22x14二值圖拉成308維向量輸入BP網(wǎng)絡(luò) trainX reshape(sampleImgs, 308, []); % 每列一個(gè)樣本共308維 net feedforwardnet(60); % 單隱含層60個(gè)神經(jīng)元 net train(net, trainX, trainY); % trainY是類別標(biāo)簽的獨(dú)熱編碼注意報(bào)告把樣本分成漢字、字母、字母數(shù)字、數(shù)字四組分別訓(xùn)練四個(gè)子網(wǎng)。原因是漢字類別多且結(jié)構(gòu)復(fù)雜字母和數(shù)字存在大量相似形比如0和O、1和I混在一起訓(xùn)練會(huì)讓網(wǎng)絡(luò)難以收斂。拆成子網(wǎng)后每個(gè)子網(wǎng)的類別數(shù)減少類間距離更大識(shí)別率能明顯提升。直接用像素向量訓(xùn)練的好處是不用手工設(shè)計(jì)特征壞處是需要的樣本量很大。課設(shè)級(jí)別的樣本量每類幾十張下效果未必比模板匹配好。實(shí)際復(fù)現(xiàn)時(shí)我建議先用模板匹配跑通全流程再視識(shí)別率決定要不要上神經(jīng)網(wǎng)絡(luò)。5.3 失敗案例復(fù)盤(pán)G→B、K→A、0→8 的根因報(bào)告里有一個(gè)很有價(jià)值的失敗案例某次識(shí)別把“G”誤識(shí)成“B”“K”誤識(shí)成“A”“0”識(shí)別成“8”。這三類錯(cuò)誤代表了模板匹配的三種典型失敗模式。G和B在22×14分辨率下實(shí)在太像右側(cè)都是豎線加弧線唯一明顯區(qū)別是B中間有一橫隔出兩個(gè)孔G沒(méi)有。如果模板匹配只看整體像素差這兩個(gè)字符的SAD誤差會(huì)非常接近。K和A同理左側(cè)豎線加右側(cè)斜線的骨架幾乎重疊區(qū)別只在K的斜線更低、A有一橫。0識(shí)別成8則通常是分割階段的問(wèn)題——字符0內(nèi)部殘留了噪點(diǎn)二值化后噪點(diǎn)把0的中間連了一條橫杠0就變成了8。這三類錯(cuò)誤提示一個(gè)關(guān)鍵原則識(shí)別錯(cuò)了先別急著換識(shí)別算法把二值化后的字符圖打出來(lái)看。如果字符本身是臟的、斷的、粘連的再?gòu)?qiáng)的識(shí)別器也救不回來(lái)。匹配前加一步重心對(duì)齊把歸一化字符的白色像素重心平移到圖像中心能緩解筆畫(huà)粗細(xì)不均帶來(lái)的整體偏移誤差再用bweuler計(jì)算字符的歐拉數(shù)連通域數(shù)減孔洞數(shù)把B、8這類雙孔字符和G、0這類少孔字符先分開(kāi)再做模板匹配能顯著壓低相似字符的誤判。6. 換個(gè)底板就翻車避坑清單與再工程驗(yàn)證這套報(bào)告默認(rèn)處理藍(lán)底白字車牌。實(shí)際復(fù)現(xiàn)時(shí)代碼里還有幾處“時(shí)代印記”和“環(huán)境依賴”直接把報(bào)告代碼跑起來(lái)大概率會(huì)斷。下面是照著復(fù)現(xiàn)時(shí)最值得注意的四類問(wèn)題。6.1 四條常見(jiàn)問(wèn)題現(xiàn)象1新版Matlab運(yùn)行到imfeature直接報(bào)錯(cuò)。原因imfeature是遠(yuǎn)古接口在新版本中已被regionprops完全替代。解決把Feastats imfeature(L,basic)改為stats regionprops(L,Area,BoundingBox)字段名Area和BoundingBox不變?nèi)≈捣绞綇腫Feastats.Area]改為[stats.Area]?,F(xiàn)象2二值化后字符變成黑色背景變成白色。原因level公式假設(shè)字符比背景亮。遇到車身亮、車牌在陰影里時(shí)字符灰度低于底板二值化結(jié)果整體反轉(zhuǎn)。解決先打印增強(qiáng)圖Egray確認(rèn)字符和底板的灰度關(guān)系。如果反轉(zhuǎn)了在二值化后加一行bw2 1 - bw2?,F(xiàn)象3旋轉(zhuǎn)校正后車牌上下邊框被裁掉字符缺一半。原因imrotate(..., crop)在旋轉(zhuǎn)角度大時(shí)會(huì)把四角空白裁掉同時(shí)把有效字符行也切了。解決旋轉(zhuǎn)前先用padarray向四周擴(kuò)一圈轉(zhuǎn)完再按投影結(jié)果取有效行。sbw_pad padarray(sbw1, [20 20], 0, both); sbw imrotate(sbw_pad, angle, bilinear, crop); % 旋轉(zhuǎn)后重新做水平投影取rowtop/rowbot不要沿用原來(lái)的值現(xiàn)象4識(shí)別結(jié)果反復(fù)把0輸出成8把G輸出成B。原因模板庫(kù)樣本太少、沒(méi)有做字符重心對(duì)齊、相似字符缺少粗分類。解決匹配前把字符白色像素重心平移到中心再用歐拉數(shù)分桶雙孔字符單獨(dú)建庫(kù)單孔和無(wú)孔字符分兩組匹配。這一步對(duì)0/8、G/B這類組合的改善非常明顯。6.2 換底板顏色與完整驗(yàn)證流程報(bào)告總結(jié)里寫(xiě)了一句很關(guān)鍵但容易被忽略的話算法對(duì)黑底白字車牌原則上可直接適用對(duì)白底黑字、黃底黑字車牌需要調(diào)整定位算法并將圖像反轉(zhuǎn)0變1、1變0。實(shí)操時(shí)白底黑字只需在二值化前后把圖反過(guò)來(lái)就行bw2 ~bw2。黃底黑字除了反色定位階段還要把基于“車牌區(qū)域相對(duì)暗”的假設(shè)改成基于邊緣密度因?yàn)辄S色底板在灰度圖上亮度很高和車身反光區(qū)域難區(qū)分。驗(yàn)證流程建議做成一個(gè)固定的檢查順序測(cè)試場(chǎng)景預(yù)期結(jié)果關(guān)鍵檢查點(diǎn)正對(duì)、光照均勻直接識(shí)別成功二值圖字符完整水平傾斜5~10度校正后分割成功擬合角度正負(fù)正確陰影遮擋一半車牌增強(qiáng)后仍能定位閾值level是否被拉高字符污損或褪色分割存在斷筆模板匹配誤差偏大我的習(xí)慣是把每張測(cè)試圖的中間結(jié)果全部落盤(pán)level值、候選區(qū)寬高比、旋轉(zhuǎn)角度、每個(gè)字符的匹配誤差前三名。這樣識(shí)別錯(cuò)了翻日志就能定位是哪一步掛的而不是對(duì)著最終結(jié)果瞎猜。從那以后我每次跑這種定位-分割-識(shí)別流程都強(qiáng)制走一遍“先把中間結(jié)果全部落盤(pán)、再談識(shí)別率”的流程。很多識(shí)別錯(cuò)誤不是算法不行是前面某一步的參數(shù)被環(huán)境帶偏了打印出中間圖十分鐘就能找到斷點(diǎn)。這套Matlab車牌識(shí)別課程設(shè)計(jì)的代碼和報(bào)告適合作為你第一個(gè)圖像識(shí)別全流程的練手項(xiàng)目希望幫到你。本文還有配套的精品資源點(diǎn)擊獲取