計算機競賽 python+opencv+機器學習車牌識別

0 前言

🔥 優質競賽項目系列,今天要分享的是

🚩 基于機器學習的車牌識別系統

🥇學長這里給一個題目綜合評分(每項滿分5分)

  • 難度系數:4分
  • 工作量:4分
  • 創新點:3分

該項目較為新穎,適合作為競賽課題方向,學長非常推薦!

🧿 更多資料, 項目分享:

https://gitee.com/dancheng-senior/postgraduate


1 課題介紹

1.1 系統簡介

車牌識別這個系統,雖然傳統,古老,卻是包含了所有這四個特偵的一個大數據技術的縮影.

在車牌識別中,你需要處理的數據是圖像中海量的像素單元;你處理的數據不再是傳統的結構化數據,而是圖像這種復雜的數據;如果不能在很短的時間內識別出車牌,那么系統就缺少意義;雖然一副圖像中有很多的信息,但可能僅僅只有那一小塊的信息(車牌)以及車身的顏色是你關心,而且這些信息都蘊含著巨大的價值。也就是說,車牌識別系統事實上就是現在火熱的大數據技術在某個領域的一個聚焦,通過了解車牌識別系統,可以很好的幫助你理解大數據技術的內涵,也能清楚的認識到大數據的價值。

1.2 系統要求

  • 它基于openCV這個開源庫,這意味著所有它的代碼都可以輕易的獲取。
  • 它能夠識別中文,例如車牌為蘇EUK722的圖片,它可以準確地輸出std:string類型的"蘇EUK722"的結果。
  • 它的識別率較高。目前情況下,字符識別已經可以達到90%以上的精度。

1.3 系統架構

整體包含兩個系統:

  • 車牌檢測
  • 車牌字體識別(中文 + 數字 + 英文)

整體架構如下:
在這里插入圖片描述

2 實現方式

2.1 車牌檢測技術

車牌檢測(Plate Detection):

對一個包含車牌的圖像進行分析,最終截取出只包含車牌的一個圖塊。這個步驟的主要目的是降低了在車牌識別過程中的計算量。如果直接對原始的圖像進行車牌識別,會非常的慢,因此需要檢測的過程。在本系統中,我們使用SVM(支持向量機)這個機器學習算法去判別截取的圖塊是否是真的“車牌”。

車牌檢測這里不詳細說明, 只貼出opencv圖像處理流程, 需要代碼的可以留下郵箱

在這里插入圖片描述
使用到的圖像處理算法

  • 高斯模糊
  • 灰度化處理
  • Sobel算子(邊緣檢測)
  • 開操作
  • 閉操作
  • 仿射變換
  • 霍姆線性檢測
  • 角度矯正

2.2 車牌識別技術

字符識別(Chars Recognition):

有的書上也叫Plate
Recognition,我為了與整個系統的名稱做區分,所以改為此名字。這個步驟的主要目的就是從上一個車牌檢測步驟中獲取到的車牌圖像,進行光學字符識別(OCR)這個過程。其中用到的機器學習算法是著名的人工神經網絡(ANN)中的多層感知機(MLP)模型。最近一段時間非常火的“深度學習”其實就是多隱層的人工神經網絡,與其有非常緊密的聯系。通過了解光學字符識別(OCR)這個過程,也可以知曉深度學習所基于的人工神經網路技術的一些內容。

我們這里使用深度學習的方式來對車牌字符進行識別, 為什么不用傳統的機器學習進行識別呢, 看圖就知道了:
在這里插入圖片描述
圖2 深度學習(右)與PCA技術(左)的對比
可以看出深度學習對于數據的分類能力的優勢。

這里博主使用生成對抗網絡進行字符識別訓練, 效果相當不錯, 識別精度達到了98%

在這里插入圖片描述

2.3 SVM識別字符

定義

    class SVM(StatModel):def __init__(self, C = 1, gamma = 0.5):self.model = cv2.ml.SVM_create()self.model.setGamma(gamma)self.model.setC(C)self.model.setKernel(cv2.ml.SVM_RBF)self.model.setType(cv2.ml.SVM_C_SVC)#訓練svmdef train(self, samples, responses):self.model.train(samples, cv2.ml.ROW_SAMPLE, responses)

?

調用方法,喂數據

    def train_svm(self):#識別英文字母和數字self.model = SVM(C=1, gamma=0.5)#識別中文self.modelchinese = SVM(C=1, gamma=0.5)if os.path.exists("svm.dat"):self.model.load("svm.dat")

訓練,保存模型

    
?    		else:
?    			chars_train = []
?    			chars_label = []
?    			for root, dirs, files in os.walk("train\\chars2"):if len(os.path.basename(root)) > 1:continueroot_int = ord(os.path.basename(root))for filename in files:filepath = os.path.join(root,filename)digit_img = cv2.imread(filepath)digit_img = cv2.cvtColor(digit_img, cv2.COLOR_BGR2GRAY)chars_train.append(digit_img)#chars_label.append(1)chars_label.append(root_int)chars_train = list(map(deskew, chars_train))chars_train = preprocess_hog(chars_train)#chars_train = chars_train.reshape(-1, 20, 20).astype(np.float32)chars_label = np.array(chars_label)print(chars_train.shape)self.model.train(chars_train, chars_label)?    

車牌字符數據集如下

在這里插入圖片描述
在這里插入圖片描述

這些是字母的訓練數據,同樣的還有我們車牌的省份簡寫:

在這里插入圖片描述

在這里插入圖片描述

核心代碼

?

   predict_result = []roi = Nonecard_color = Nonefor i, color in enumerate(colors):if color in ("blue", "yello", "green"):card_img = card_imgs[i]gray_img = cv2.cvtColor(card_img, cv2.COLOR_BGR2GRAY)#黃、綠車牌字符比背景暗、與藍車牌剛好相反,所以黃、綠車牌需要反向if color == "green" or color == "yello":gray_img = cv2.bitwise_not(gray_img)ret, gray_img = cv2.threshold(gray_img, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)#查找水平直方圖波峰x_histogram  = np.sum(gray_img, axis=1)x_min = np.min(x_histogram)x_average = np.sum(x_histogram)/x_histogram.shape[0]x_threshold = (x_min + x_average)/2wave_peaks = find_waves(x_threshold, x_histogram)if len(wave_peaks) == 0:print("peak less 0:")continue#認為水平方向,最大的波峰為車牌區域wave = max(wave_peaks, key=lambda x:x[1]-x[0])gray_img = gray_img[wave[0]:wave[1]]#查找垂直直方圖波峰row_num, col_num= gray_img.shape[:2]#去掉車牌上下邊緣1個像素,避免白邊影響閾值判斷gray_img = gray_img[1:row_num-1]y_histogram = np.sum(gray_img, axis=0)y_min = np.min(y_histogram)y_average = np.sum(y_histogram)/y_histogram.shape[0]y_threshold = (y_min + y_average)/5#U和0要求閾值偏小,否則U和0會被分成兩半wave_peaks = find_waves(y_threshold, y_histogram)#for wave in wave_peaks:#	cv2.line(card_img, pt1=(wave[0], 5), pt2=(wave[1], 5), color=(0, 0, 255), thickness=2) #車牌字符數應大于6if len(wave_peaks) <= 6:print("peak less 1:", len(wave_peaks))continuewave = max(wave_peaks, key=lambda x:x[1]-x[0])max_wave_dis = wave[1] - wave[0]#判斷是否是左側車牌邊緣if wave_peaks[0][1] - wave_peaks[0][0] < max_wave_dis/3 and wave_peaks[0][0] == 0:wave_peaks.pop(0)#組合分離漢字cur_dis = 0for i,wave in enumerate(wave_peaks):if wave[1] - wave[0] + cur_dis > max_wave_dis * 0.6:breakelse:cur_dis += wave[1] - wave[0]if i > 0:wave = (wave_peaks[0][0], wave_peaks[i][1])wave_peaks = wave_peaks[i+1:]wave_peaks.insert(0, wave)#去除車牌上的分隔點point = wave_peaks[2]if point[1] - point[0] < max_wave_dis/3:point_img = gray_img[:,point[0]:point[1]]if np.mean(point_img) < 255/5:wave_peaks.pop(2)if len(wave_peaks) <= 6:print("peak less 2:", len(wave_peaks))continuepart_cards = seperate_card(gray_img, wave_peaks)for i, part_card in enumerate(part_cards):#可能是固定車牌的鉚釘if np.mean(part_card) < 255/5:print("a point")continuepart_card_old = part_cardw = abs(part_card.shape[1] - SZ)//2part_card = cv2.copyMakeBorder(part_card, 0, 0, w, w, cv2.BORDER_CONSTANT, value = [0,0,0])part_card = cv2.resize(part_card, (SZ, SZ), interpolation=cv2.INTER_AREA)#part_card = deskew(part_card)part_card = preprocess_hog([part_card])if i == 0:resp = self.modelchinese.predict(part_card)charactor = provinces[int(resp[0]) - PROVINCE_START]else:resp = self.model.predict(part_card)charactor = chr(resp[0])#判斷最后一個數是否是車牌邊緣,假設車牌邊緣被認為是1if charactor == "1" and i == len(part_cards)-1:if part_card_old.shape[0]/part_card_old.shape[1] >= 7:#1太細,認為是邊緣continuepredict_result.append(charactor)roi = card_imgcard_color = colorbreakreturn predict_result, roi, card_color#識別到的字符、定位的車牌圖像、車牌顏色?    

?

2.4 最終效果

最后算法部分可以和你想要的任何UI配置到一起:

可以這樣 :
在這里插入圖片描述

也可以這樣:
在這里插入圖片描述

甚至更加復雜一點:
在這里插入圖片描述

最后

🧿 更多資料, 項目分享:

https://gitee.com/dancheng-senior/postgraduate

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/38741.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/38741.shtml
英文地址,請注明出處:http://en.pswp.cn/news/38741.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

使用插件實現pdf,word預覽功能

效果 代碼&#xff1a; 插件地址&#xff1a; https://github.com/501351981/vue-office <a-modalv-model:visible"visible":title"title"ok"handleOk":bodyStyle"bodyStyle":width"1200":maskClosable"false"…

如何在Vue表單處理中實現表單的條件渲染

在Vue開發中&#xff0c;我們經常會遇到需要根據某些條件來渲染表單的情況。這種情況下&#xff0c;我們需要靈活地根據條件來展示或隱藏一些表單字段。本文將介紹如何在Vue中實現表單的條件渲染&#xff0c;并提供了代碼示例。 一、使用v-if指令實現簡單的條件渲染 在Vue中&a…

2023年網絡安全比賽--綜合滲透測試(超詳細)

一、競賽時間 180分鐘 共計3小時 二、競賽階段 競賽階段 任務階段 競賽任務 競賽時間 分值 1.掃描目標靶機將靶機開放的所有端口,當作flag提交(例:21,22,23); 2.掃描目標靶機將靶機的http服務版本信息當作flag提交(例:apache 2.3.4); 3.靶機網站存在目錄遍歷漏洞,請將…

Linux設備樹詳解

Linux 設備樹詳解 Linux 操作系統早期是針對個人電腦設備而開發的操作系統&#xff0c;而個人電腦處理器產商較為單一&#xff08;例如只有 Intel&#xff0c;AMD&#xff09;同時個人電腦產商均使用 Intel 或 AMD 制造的處理器&#xff0c;業界形成了統一的總線/硬件接口標準…

JavaScript進階 第二天

深入對象內置構造函數 一. 深入對象 創建對象三種方式構造函數實例成員&靜態成員 1.1 創建對象三種方式 ① 利用對象字面量創建對象 const o {name: 哈哈 } ② 利用new Object 創建對象 const o new Object({ name: 哈哈 }) ③ 構造函數創建對象 1.2 構造函數 …

探索規律:Python地圖數據可視化藝術

文章目錄 一 基礎地圖使用二 國內疫情可視化圖表2.1 實現步驟2.2 完整代碼2.3 運行結果 一 基礎地圖使用 使用 Pyecharts 構建地圖可視化也是很簡單的。Pyecharts 支持多種地圖類型&#xff0c;包括普通地圖、熱力圖、散點地圖等。以下是一個構建簡單地圖的示例&#xff0c;以…

認識Transformer:入門知識

視頻鏈接&#xff1a; https://www.youtube.com/watch?vugWDIIOHtPA&listPLJV_el3uVTsOK_ZK5L0Iv_EQoL1JefRL4&index60 文章目錄 Self-Attention layerMulti-head self-attentionPositional encodingSeq2Seq with AttentionTransformerUniversal Transformer Seq2Seq …

淺談 EMP-SSL + 代碼解讀:自監督對比學習的一種極簡主義風

論文鏈接&#xff1a;https://arxiv.org/pdf/2304.03977.pdf 代碼&#xff1a;https://github.com/tsb0601/EMP-SSL 其他學習鏈接&#xff1a;突破自監督學習效率極限&#xff01;馬毅、LeCun聯合發布EMP-SSL&#xff1a;無需花哨trick&#xff0c;30個epoch即可實現SOTA 主要…

08 qt進程和網絡編程(cs模型)

一 、qt進程 qt中進程最主要的任務就是啟動額外應用程序 并且跟他們之間通信。進程類為QProcess 定義用途Header:#include qmake:QT += coreInherits:QIODevice//繼承于IO設備類1.1 QProcess基本使用 第一步:創建一個QProcess對象 // process = new QProcess(this); //說明…

資訊速遞 | ArkUI-X 預覽版已正式開源!

OpenHarmony項目群技術指導委員會&#xff08;以下簡稱“TSC”&#xff09;-跨平臺應用開發框架TSG所孵化項目 —— ArkUI-X&#xff0c;近期已正式開源 &#xff0c;開發者基于一套主代碼&#xff0c;就可以將在OpenHarmony上開發的精美、高性能應用同時運行在Android、iOS等其…

LNMP環境搭建wordpress以及跳轉后臺報404解決

基于上文配置好的LNMP環境繼續搭建wordpress 目錄 一.到官網下載tar.gz包&#xff0c;并上傳到Linux上&#xff0c;也可以通過復制鏈接地址進行下載 二. 將wordpress中的所有文件移動到你nginx.conf中指定目錄中 三.為wordpress配置數據庫 四.到瀏覽器進行注冊 1.剛開始…

maven編譯始終提示無效的目標發行版的解決方法

摘自個人印象筆記2021-05-07&#xff1a;https://app.yinxiang.com/fx/55e1d5f4-aeea-446a-a768-0f1a48195f5b(圖顯示不完整可查看原筆記內容)1&#xff1a;確保IDE中的編譯版本正確 在idea中&#xff0c;主要看項目屬性中和setting的java compiler中對應的jdk版本是否正確&…

好用的安卓手機投屏到mac分享

工具推薦&#xff1a;scrcpy github地址&#xff1a;https://github.com/Genymobile/scrcpy/tree/master mac使用方式 安裝環境&#xff0c;打開terminal&#xff0c;執行以下命令&#xff0c;沒有brew的先安裝brew brew install scrcpy brew install android-platform-too…

學習 Iterator 迭代器

今天看到一個面試題&#xff0c; 讓下面解構賦值成立。 let [a,b] {a:1,b:2} 如果我們直接在瀏覽器輸出這行代碼&#xff0c;會直接報錯&#xff0c;說是 {a:1,b:2} 不能迭代。 看了es6文檔后&#xff0c;具有迭代器的就一下幾種類型&#xff0c;沒有Object類型&#xff0c;…

404. 左葉子之和

給定二叉樹的根節點 root &#xff0c;返回所有左葉子之和。 示例 1&#xff1a; 輸入: root [3,9,20,null,null,15,7] 輸出: 24 解釋: 在這個二叉樹中&#xff0c;有兩個左葉子&#xff0c;分別是 9 和 15&#xff0c;所以返回 24示例 2: 輸入: root [1] 輸出: 0提示: 節點…

【NetCore】09-中間件

文章目錄 中間件&#xff1a;掌控請求處理過程的關鍵1. 中間件1.1 中間件工作原理1.2 中間件核心對象 2.異常處理中間件:區分真異常和邏輯異常2.1 處理異常的方式2.1.1 日常錯誤處理--定義錯誤頁的方法2.1.2 使用代理方法處理異常2.1.3 異常過濾器 IExceptionFilter2.1.4 特性過…

go web框架 gin-gonic源碼解讀02————router

go web框架 gin-gonic源碼解讀02————router 本來想先寫context&#xff0c;但是發現context能簡單講講的東西不多&#xff0c;就準備直接和router合在一起講好了 router是web服務的路由&#xff0c;是指講來自客戶端的http請求與服務器端的處理邏輯或者資源相映射的機制。&…

react實現對數組做增刪改操作自定義hook

需求 實現對數組的增刪改操作。 實現 import { useState } from react;const useArray (currList) > {const [list, setList] useState(currList);// 增const addItem (item) > {setList([...list, item]);};// 刪const removeItem (idx) > {const _arr [...l…

實戰指南,SpringBoot + Mybatis 如何對接多數據源

系列文章目錄 MyBatis緩存原理 Mybatis plugin 的使用及原理 MyBatisSpringboot 啟動到SQL執行全流程 數據庫操作不再困難&#xff0c;MyBatis動態Sql標簽解析 從零開始&#xff0c;手把手教你搭建Spring Boot后臺工程并說明 Spring框架與SpringBoot的關聯與區別 Spring監聽器…

輕松解決docker容器啟動閃退

docker run -p 3306:3306 --name mysql8 \ -v /usr/local/mysql/log:/var/log/mysql \ -v /usr/local/mysql/data:/var/lib/mysql \ -v /usr/local/mysql/conf:/etc/mysql \ -e MYSQL_ROOT_PASSWORD666 -d mysql:8.0.32執行這個命令的時候閃退&#xff0c;其實這個是命令是對你…