生活随笔
收集整理的這篇文章主要介紹了
车牌识别之颜色选取
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
車牌定位是車牌識(shí)別中第一步,也是最重要的一步。
由于中國車牌種類多樣,顏色不一, 再加上車牌經(jīng)常有污損,以及車牌周圍干擾因素太多,都成為了車牌定位的難點(diǎn)。
這里首先使用最簡單算法來描述車牌定位,以及他的缺陷和改進(jìn)。
一、投影法
1、車輛圖像信息獲取
2、HSV顏色轉(zhuǎn)換
把RGB數(shù)據(jù)轉(zhuǎn)換成HSV空間圖像數(shù)據(jù)
hsvzation(image,hsv,width,height);
3、HSV顏色過濾
設(shè)置藍(lán)色車牌底色閾值范圍,進(jìn)行顏色過濾
藍(lán)色車牌
H值范圍:190 ~ 245
S值范圍: 0.35 ~ 1
V值范圍: 0.3 ~ 1
過濾后圖像如下:
4、噪聲處理
過濾后,一般要進(jìn)行去噪處理,這里早點(diǎn)不明顯,如果車牌周圍有藍(lán)色物體,噪點(diǎn)就非常明顯了
這里使用平均去噪,一些孤立白點(diǎn)將被去除,效果如下:
5、邊緣檢測
去噪后,進(jìn)行邊緣檢測,邊緣檢測的目的就是為了突出車牌信息的突變,因?yàn)檐嚺票尘昂妥煮w顏色區(qū)分開了;
這樣做的目的也是為了防止周圍有和車牌底色相同顏色的物體干擾,尤其是車輛顏色,因?yàn)榻?jīng)過邊緣檢測后車體顏色沒有那么多跳變干擾或者與車牌跳變規(guī)律不一樣,這樣就可以濾去車體顏色,去除干擾
6、確定車牌位置
通過水平投影和垂直投影確定車牌位置。
(這里投影方法有很大缺陷,在車牌周圍除了車輛還有其他背景信息時(shí)尤為明顯,這在下面的另一種方法中改善)
7、截取車牌圖像
二、投影法定位缺陷示例
1、讀取復(fù)雜背景的車牌圖像
2、HSV濾波
HSV過濾后可以看到明顯的干擾信息,車輛后面的欄桿,和車輛同樣的顏色
3、均值去噪
去噪后,雖然大部分噪點(diǎn)都去除了,但是欄桿依然清晰
4、邊緣檢測
邊緣檢測后的圖像,車牌區(qū)域的形狀特征,給我們解決投影缺陷的一些啟示
5,、 投影后錯(cuò)誤的定位
6、車牌提取錯(cuò)誤
后半塊車身,比例也不符合車牌特征
由此看見,在復(fù)雜背景的車牌識(shí)別中,全局投影就無法抑制干擾,在下面黃色車牌示例中就更加明顯;
投影法簡單,但只是在只有整體車輛信息,沒有復(fù)雜背景信息的時(shí)候才可以使用。
三、基于候選區(qū)域判斷方法
這個(gè)方法放棄了投影,直接遍歷整個(gè)圖像信息,檢查每個(gè)聯(lián)通域的長度和寬度,當(dāng)符合車牌的寬高比時(shí),才選定為候選區(qū)域,由后面處理流程進(jìn)行處理,來判斷是否能夠提取正常的字符。
前兩個(gè)步驟還是同上面一樣的。
1、HSV空間轉(zhuǎn)換
2、均值去噪
3、水平膨脹
目的:盡可能的形成連通域
4、邊緣檢測
也可以不用邊緣檢測,這里主要考慮到 盡量減少 圖像白點(diǎn) 遍歷中的運(yùn)算
5、候選區(qū)域篩選
候選區(qū)域篩選,?這是區(qū)別投影方法的主要部分,
從上圖可以看出有幾個(gè)候選區(qū)域,大概有4塊, 而中間的車牌有明顯矩形特征,符合一定的長寬比例, 其他三塊區(qū)域不具備這樣的特征,在篩選的過程中予以舍棄。
篩選的方法采用 深度優(yōu)先遍歷, 當(dāng)遇到連通域時(shí),記錄他的長度和高度,并設(shè)定閾值,當(dāng)符合長寬比時(shí),才會(huì)選中為候選區(qū)域,否則予以舍棄,當(dāng)然還可以添加別的算法,比如檢測跳變,畢竟符合這一比率的不一定就是車牌區(qū)域。
下圖中黃框就是篩選后的區(qū)域:
連通域篩選函數(shù)如下:
[cpp]?view plaincopy
int?find_connected_region_location(struct?BMP_img?*img,?unsigned?char?*src,?int?xthreashold,?int?ythreashold,?float?rateLow,?float?rateHigh)?? {?? ????int?i,j;?? ????int?x1,?y1,?x2,?y2;?? ????int?width;?? ????int?height;?? ????unsigned?char?*temp;?? ?????? ????int?head,?rear;?? ????struct?XY_Queue?*queue;?? ????static?int?direction[4][2]={{1,?0},?{-1,?0},?{0,?1},?{0,?-1}};?? ?? ????width?=?img->width;?? ????height?=?img->height;?? ?? ????queue?=?(struct?XY_Queue?*)malloc(sizeof(struct?XY_Queue)?*?width?*?height);?? ?? ????temp?=?(unsigned?char?*)malloc(width?*?height?*?sizeof(unsigned?char));?? ?? ????if(temp?==?NULL)?? ????{?? ????????printf("find_connected_region_location?mem?alloc?fail\n");?? ????????return?-1;?? ????}?? ????memcpy(temp,?src,?width?*?height);?? ?? ????head?=?rear?=?0;?? ????img->region_num?=?0;?? ?? ????for(i?=?0;?i?<?height;?i++)?? ????????for(j?=?0;?j?<?width;?j++)?? ????{?? ????????if(temp[i?*?width?+?j]?==?255)?? ????????{?? ?????????????????????? ????????????queue[rear].x?=?j;?? ????????????queue[rear].y?=?i;?? ????????????rear?++;?? ????????????temp[i?*?width?+?j]?=?0;?? ?? ????????????img->pre_region[img->region_num].x1?=?j;?? ????????????img->pre_region[img->region_num].x2?=?j;?? ????????????img->pre_region[img->region_num].y1?=?i;?? ????????????img->pre_region[img->region_num].y2?=?i;?? ?? ????????????if(img->region_num?>?CAN_REGION_NUM)?? ????????????{?? ????????????????printf("over?the?CAN_REGION_NUM\n");?? ????????????????return?-1;?? ????????????}?? ?? ????????????while(head?<?rear)?? ????????????{?? ????????????????x1?=?queue[head].x;?? ????????????????y1?=?queue[head].y;?? ????????????????head?++;?? ?? ????????????????if(x1?<?img->pre_region[img->region_num].x1)?? ????????????????????img->pre_region[img->region_num].x1?=?x1;?? ????????????????else?if(x1?>?img->pre_region[img->region_num].x2)?? ????????????????????img->pre_region[img->region_num].x2?=?x1;?? ????????????????if(y1?<?img->pre_region[img->region_num].y1)?? ????????????????????img->pre_region[img->region_num].y1?=?y1;?? ????????????????else?if(y1?>?img->pre_region[img->region_num].y2)?? ????????????????????img->pre_region[img->region_num].y2?=?y1;?? ?????????????????? ?????? ????????????????for(i?=?0;?i?<?4;?i++)?? ????????????????{?? ????????????????????x2?=?x1?+?direction[i][0];?? ????????????????????y2?=?y1?+?direction[i][1];?? ?? ????????????????????if(x2?>?0?&&?x2?<?width?&&?y2?>?0?&&?y2?<?height?&&?temp[y2?*?width?+?x2])?? ????????????????????{?? ????????????????????????temp[y2?*?width?+?x2]?=?0;?? ????????????????????????queue[rear].x?=?x2;?? ????????????????????????queue[rear].y?=?y2;?? ????????????????????????rear?++;?? ????????????????????}?? ?????????????? ????????????????}?? ????????????}?? ????????????if((img->pre_region[img->region_num].x2?-?img->pre_region[img->region_num].x1?>?xthreashold)?&&?(img->pre_region[img->region_num].y2?-?img->pre_region[img->region_num].y1?>?ythreashold))?? ????????????{?? ?? ????????????????img->pre_region[img->region_num].width?=?img->pre_region[img->region_num].x2?-?img->pre_region[img->region_num].x1?+?1;?? ????????????????img->pre_region[img->region_num].height?=?img->pre_region[img->region_num].y2?-?img->pre_region[img->region_num].y1?+?1;?? ????????????????img->pre_region[img->region_num].rate?=?(float)img->pre_region[img->region_num].width/img->pre_region[img->region_num].height;?? ????????????????if((img->pre_region[img->region_num].width?<?img->width?/?2)?&&?(img->pre_region[img->region_num].height?<?img->height?/?2))?? ????????????????if((img->pre_region[img->region_num].rate?>?rateLow)?&&?(img->pre_region[img->region_num].rate?<?rateHigh))?? ????????????????{?? ????????????????????if(img->pre_region[img->region_num].x2?+?PRE_LOCATION_BIAS?>?img->width)?? ????????????????????????????img->pre_region[img->region_num].x2?=?img->width;?? ????????????????????else?? ????????????????????????????img->pre_region[img->region_num].x2?+=?PRE_LOCATION_BIAS;?? ????????????????????if(img->pre_region[img->region_num].x1?-?PRE_LOCATION_BIAS?<?0)?? ????????????????????????????img->pre_region[img->region_num].x1?=?0;?? ????????????????????else?? ????????????????????????????img->pre_region[img->region_num].x1?-=?PRE_LOCATION_BIAS;?? ????????????????????if(img->pre_region[img->region_num].y2?+?PRE_LOCATION_BIAS?>?img->height)?? ????????????????????????????img->pre_region[img->region_num].y2?=?img->height;?? ????????????????????else?? ????????????????????????????img->pre_region[img->region_num].y2?+=?PRE_LOCATION_BIAS;?? ????????????????????if(img->pre_region[img->region_num].y1?-?PRE_LOCATION_BIAS?<?0)?? ????????????????????????????img->pre_region[img->region_num].y1?=?0;?? ????????????????????else?? ????????????????????????????img->pre_region[img->region_num].y1?-=?PRE_LOCATION_BIAS;?? ?? ????????????????????img->pre_region[img->region_num].width?=?img->pre_region[img->region_num].x2?-?img->pre_region[img->region_num].x1?+?1;?? ????????????????????img->pre_region[img->region_num].height?=?img->pre_region[img->region_num].y2?-?img->pre_region[img->region_num].y1?+?1;?? ?????????????? ????????????????????img->region_num++;?? ????????????????}?? ????????????}?? ????????}?? ?????????? ?????????? ????}?? ????free(temp);?? ????temp?=?NULL;?? ????return?0;?? }??
6、截取車牌區(qū)域圖像
四、黃色車牌檢測
1、車輛圖像信息
2、HSV過濾分割
由于車牌顏色 與 車輛顏色一直,出現(xiàn)大量噪聲信息,全局投影已不可能分割出車牌信息了,
這里只是 利用候選區(qū)域長寬比來進(jìn)行矩形分割,肯定會(huì)出現(xiàn)一些符合比例但是不是車牌的區(qū)域,必須在后面的處理中加以區(qū)分或者添加判斷跳變規(guī)律的函數(shù)
3、去噪
4、 膨脹
6、邊緣檢測
7、候選區(qū)域 連通域篩選
從圖中可以看到黃框 部分即是符合候選區(qū)域的地方
8、截取候選區(qū)域
此候選區(qū)域只是符合長寬比,需要另行處理 除去不是車牌的區(qū)域
五、小結(jié)
車牌定位比較復(fù)雜,但對于車牌識(shí)別來說,最為重要,我認(rèn)為它是影響車牌識(shí)別最大因素。雖然復(fù)雜,但是方法多種多樣。
這里僅此個(gè)人愛好和研究,希望各位朋友繼續(xù)提出批評和建議,大家的鼓勵(lì)給了我堅(jiān)持下去的勇氣。
總結(jié)
以上是生活随笔為你收集整理的车牌识别之颜色选取的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。