【毕业设计】stm32实现车牌识别系统 -物联网 嵌入式 单片机
文章目錄
- 0 前言
- 1 簡介
- 2 主要器件
- 3 實現效果
- 4 設計原理
- 4.1 **軟件總體過程:**
- 4.2 具體解釋
- 5 部分核心代碼
- 6 最后
0 前言
🔥 這兩年開始畢業設計和畢業答辯的要求和難度不斷提升,傳統的畢設題目缺少創新和亮點,往往達不到畢業答辯的要求,這兩年不斷有學弟學妹告訴學長自己做的項目系統達不到老師的要求。
為了大家能夠順利以及最少的精力通過畢設,學長分享優質畢業設計項目,今天要分享的是
🚩 基于stm32的實現車牌識別系統
🥇學長這里給一個題目綜合評分(每項滿分5分)
- 難度系數:4分
- 工作量:4分
- 創新點:3分
🧿 選題指導, 項目分享:
https://gitee.com/dancheng-senior/project-sharing-1/blob/master/%E6%AF%95%E8%AE%BE%E6%8C%87%E5%AF%BC/README.md
1 簡介
本系統利用STM32單片機驅動攝像頭采集圖像,通過模式識別,匹配車牌的識別結果,并在屏幕上顯示。
2 主要器件
- STM32F103RCT6 主控芯片
- TFT液晶屏
- OV7670攝像頭
- 蜂鳴器
- LED電路
3 實現效果
識別效果
攝像頭模塊
4 設計原理
4.1 軟件總體過程:
(1)OV7670帶FIFO攝像頭圖像采集,采用GPIO模擬攝像頭時序,通過讀取FIFO輸出值將圖像直接顯示在LCD屏上
(2)LCD屏相當于一個圖像緩存,同時也做顯示,通過讀取LCD屏上的像素值進行圖像處理;
(3)車牌定位處理,車牌定位常用二值化分割,腐蝕膨脹處理,連通域計算等操作,顯然這些算法在stm32f1上實現是很困難的,且處理速度太慢,因此,采用RGB轉HSV顏色空間變換和閾值選擇進行車牌定位,然后將車牌定位區域進行二值化處理,不是藍色車牌的部分就是字符區域;
(4)車牌字符分割處理,字符分割先采用行統計加列統計的方式,確定每行和每列的有效像素和,進一步確定字符區域;然后進行橫向統計分割,通過每一列的像素和閾值判斷字符的分界線和個數;
(5)車牌歸一化處理,歸一化處理先將每個字符提取出來,然后按照像素值進行橫向和縱向壓縮,最終處理成模板一樣大小的字符;并在液晶屏上保存字符的數據;
(6)模板匹配,將歸一化之后的字符,與模板中的字符通過像素值一一比較,確定相似度最高的字符就是目標值;
4.2 具體解釋
圖像采集
通過OV7670攝像頭進行圖像采集,采集的圖像大小為320*240像素,像素格式為RGB565。每個像素由兩字節組成,第一字節的高五位是Red,第一字節的低三位和第二字節的高三位組成Green,第二字節的低五位是Blue。
二值化
二值化就是讓圖像的像素點矩陣中的每個像素點的灰度值為0(黑色)或者255(白色),讓整個圖片呈現出只有黑色和白色的效果。二值化后的圖像中灰度值范圍是0或者255。這時需要設定一個閾值來對像素點進行設置。
常用二值化方法:
識別車牌區域
根據上一步的二值化,由于車牌區域跳變點多,由此可以得出車牌區域。分別記錄車牌區域的上下高度。然后通過RGB-HSV顏色轉換,識別出車牌區域的左右邊界。
字符分割
我國常見車牌以及排列順序大部分都是按照如下設計的:漢字、英文字母、點、英文字母、阿拉伯數字、阿拉伯數字、阿拉伯數字、阿拉伯數字?;谶@個規律,以及圖像采集高度一致,設計了如下的分割方法:
字符匹配
對分割出來的字符進行歸一化處理,這里用到圖片的擴大算法,擴大之后逐一的去進行字符匹配。字符模板事前通過字模軟件轉換成二進制數據保存在數組中。最后根據匹配結果相似度最大的做為輸出結果。
歸一化圖像就是要把原來各不相同的字符統一到同一尺寸。因為掃描進來的圖像中字符大小存在較大的差異,而相對來說,統一尺寸的字符識別的標準性更強,準確率自然也更高。具體算法如下:先得到原來字符的高度和寬度,與系統已存字模的數據作比較,得出要變換的系數,然后根據得到的系數按照插值的方法映射到原圖像中。
5 部分核心代碼
#define COLOR_RGB565_TO_R8(pixel) \ ({ \ __typeof__ (pixel) __pixel = (pixel); \ __pixel = (__pixel >> 8) & 0xF8; \ __pixel | (__pixel >> 5); \ })#define COLOR_RGB565_TO_G8(pixel) \ ({ \__typeof__ (pixel) __pixel = (pixel); \__pixel = (__pixel >> 3) & 0xFC; \__pixel | (__pixel >> 6); \ }) #define COLOR_RGB565_TO_B8(pixel) \ ({ \__typeof__ (pixel) __pixel = (pixel); \__pixel = (__pixel << 3) & 0xF8; \__pixel | (__pixel >> 5); \}) int8_t imlib_rgb565_to_l(uint16_t pixel) { float r_lin = xyz_table[COLOR_RGB565_TO_R8(pixel)]; float g_lin = xyz_table[COLOR_RGB565_TO_G8(pixel)]; float b_lin = xyz_table[COLOR_RGB565_TO_B8(pixel)];float y = ((r_lin * 0.2126f) + (g_lin * 0.7152f) + (b_lin * 0.0722f)) * (1.0f / 100.000f);y = (y>0.008856f) ? fast_cbrtf(y) : ((y * 7.787037f) + 0.137931f); return fast_floorf(116 * y) - 16; }int8_t imlib_rgb565_to_a(uint16_t pixel) { float r_lin = xyz_table[COLOR_RGB565_TO_R8(pixel)]; float g_lin = xyz_table[COLOR_RGB565_TO_G8(pixel)]; float b_lin = xyz_table[COLOR_RGB565_TO_B8(pixel)];float x = ((r_lin * 0.4124f) + (g_lin * 0.3576f) + (b_lin * 0.1805f)) * (1.0f / 095.047f); float y = ((r_lin * 0.2126f) + (g_lin * 0.7152f) + (b_lin * 0.0722f)) * (1.0f / 100.000f);x = (x>0.008856f) ? fast_cbrtf(x) : ((x * 7.787037f) + 0.137931f); y = (y>0.008856f) ? fast_cbrtf(y) : ((y * 7.787037f) + 0.137931f); return fast_floorf(500 * (x-y)); }int8_t imlib_rgb565_to_b(uint16_t pixel) { float r_lin = xyz_table[COLOR_RGB565_TO_R8(pixel)]; float g_lin = xyz_table[COLOR_RGB565_TO_G8(pixel)]; float b_lin = xyz_table[COLOR_RGB565_TO_B8(pixel)]; float y = ((r_lin * 0.2126f) + (g_lin * 0.7152f) + (b_lin * 0.0722f)) * (1.0f / 100.000f); float z = ((r_lin * 0.0193f) + (g_lin * 0.1192f) + (b_lin * 0.9505f)) * (1.0f / 108.883f); y = (y>0.008856f) ? fast_cbrtf(y) : ((y * 7.787037f) + 0.137931f); z = (z>0.008856f) ? fast_cbrtf(z) : ((z * 7.787037f) + 0.137931f); return fast_floorf(200 * (y-z)); } unsigned short xrIntFloat_16=(Src_width<<8)/Dst_width+1; //擴大倍數 unsigned short yrIntFloat_16=(Src_height<<8)/Dst_height+1; unsigned char* pDstLine=Dst_y8; unsigned short srcy_16=0; for (y=0;y<Dst_height;++y) { unsigned char* pSrcLine=((unsigned char*)((unsigned char*)Src_y8+Src_width*(srcy_16>>8))); unsigned short srcx_16=0; for (x=0;x<Dst_width;++x) { pDstLine[x]=pSrcLine[srcx_16>>8]; srcx_16+=xrIntFloat_16; } srcy_16+=yrIntFloat_16; pDstLine+=Dst_width; } }模板匹配算法
/** * @function 歐幾里得距離計算,用于圖片相似度計算 * @param[in] src1和src2,必須是相同大小灰度圖片 * @param[out] 歐幾里得距離 * @retval ERROR -1 錯誤 * @par 2021年5月28日 zhengmf */ float Euclidean_Distance(unsigned char *Src1,unsigned char *Src2,int length,float Euclideandis) {if(Src1==NULL||Src2==NULL){return -1;}int sum=0;int i=0;for(i=0;i<length;i++){sum+=(int)pow((*Src1-*Src2),2);Src1++;Src2++;}Euclideandis=(float)sqrt(sum);return Euclideandis; }/** * @function 余弦相似度計算,用于圖片相似度計算 * @param[in] src1和src2,必須是相同大小灰度圖片 * @param[out] 余弦相似度 * @retval 0 相似度小于0 * @retval ERROR -1 錯誤 * @retval CosineSimilar * @par 2021年5月28日 zhengmf */ float Cosine_Similarity(unsigned char *Src1,unsigned char *Src2,int length,float CosineSimilar) {if(Src1==NULL||Src2==NULL){return -1;}int sum=0,sum1=0,sum2=0;float temp0=0,temp1=0;int i=0;for(i=0;i<length;i++){sum+=(int)(*Src1)*(*Src2);sum1+=(int)pow((*Src1),2);sum2+=(int)pow((*Src2),2);Src1++;Src2++;}if(sum<=0){return 0;}temp0=(float)(sqrt(sum1));temp1=(float)(sqrt(sum2));CosineSimilar=(float)((sum/temp0)/temp1);return CosineSimilar; }/** * @function 皮爾遜相似度計算,用于圖片相似度計算 * @param[in] src1和src2,必須是相同大小灰度圖片 * @param[out] 皮爾遜相似度 * @retval ERROR -1 錯誤 * @par 2021年5月28日 zhengmf */ float Pearson_Correlation(unsigned char *Src1,unsigned char *Src2,int length,float PearsonSimilar) {if(Src1==NULL||Src2==NULL){return -1;}unsigned char aver1=0,aver2=0;int sum=0,sum1=0,sum2=0;float temp0=0,temp1=0;int i=0;for(i=0;i<length;i++){sum1+=*Src1;sum2+=*Src2;Src1++;Src2++;}aver1=(unsigned char)(sum1/length);aver2=(unsigned char)(sum2/length);sum1=0;sum2=0;for(i=0;i<length;i++){sum+=(int)(*Src1-aver1)*(*Src2-aver2);sum1+=(int)pow((*Src1-aver1),2);sum2+=(int)pow((*Src2-aver2),2);Src1++;Src2++;}if(sum<=0){return 0;}temp0=(float)(sqrt(sum1));temp1=(float)(sqrt(sum2));PearsonSimilar=(float)((sum/temp0)/temp1); return PearsonSimilar; }6 最后
總結
以上是生活随笔為你收集整理的【毕业设计】stm32实现车牌识别系统 -物联网 嵌入式 单片机的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: shopeeman智能多店软件教你Sho
- 下一篇: C:/windows/system32无