手把手的技術(shù)干貨教程,記錄從0到1的開發(fā)過(guò)程。
一、前言
1.1 內(nèi)容簡(jiǎn)介
隨著城市化進(jìn)程的不斷加快,私家車數(shù)量迅猛增長(zhǎng),停車場(chǎng)管理面臨著巨大的壓力。傳統(tǒng)的人工管理方式效率低下,容易出現(xiàn)疏漏,不僅浪費(fèi)了人力資源,還導(dǎo)致了用戶體驗(yàn)的下降。在這種背景下,智能化停車場(chǎng)管理系統(tǒng)應(yīng)運(yùn)而生,為提升停車場(chǎng)的運(yùn)營(yíng)效率和用戶服務(wù)質(zhì)量提供了可能。
近年來(lái),車牌識(shí)別技術(shù)作為智能停車場(chǎng)的重要組成部分,得到了廣泛應(yīng)用。通過(guò)自動(dòng)識(shí)別車輛的車牌信息,可以實(shí)現(xiàn)車輛的快速進(jìn)出場(chǎng)記錄與管理,有效減少人工干預(yù),提高效率。結(jié)合云計(jì)算技術(shù),車牌識(shí)別系統(tǒng)可以進(jìn)一步實(shí)現(xiàn)數(shù)據(jù)的集中處理和管理,為停車場(chǎng)的計(jì)費(fèi)、安防等功能提供強(qiáng)大的技術(shù)支撐。
華為云作為國(guó)內(nèi)領(lǐng)先的云計(jì)算服務(wù)提供商,其提供的車牌識(shí)別服務(wù)具備高效、精準(zhǔn)的特點(diǎn),能夠滿足停車場(chǎng)系統(tǒng)對(duì)實(shí)時(shí)性和可靠性的要求。通過(guò)華為開發(fā)者空間的云主機(jī),開發(fā)者可以快速部署應(yīng)用,利用云端強(qiáng)大的計(jì)算能力和穩(wěn)定的環(huán)境,降低開發(fā)難度,提高開發(fā)效率。
本項(xiàng)目利用華為云的車牌識(shí)別服務(wù),設(shè)計(jì)并實(shí)現(xiàn)一個(gè)停車場(chǎng)自動(dòng)計(jì)費(fèi)系統(tǒng)。通過(guò)對(duì)車輛進(jìn)入和離開時(shí)間的記錄和識(shí)別,系統(tǒng)能夠自動(dòng)計(jì)算停車費(fèi)用,減少人工干預(yù),提升用戶體驗(yàn)。項(xiàng)目采用Python語(yǔ)言進(jìn)行開發(fā),結(jié)合PyQt5進(jìn)行用戶界面設(shè)計(jì),為系統(tǒng)提供簡(jiǎn)潔友好的操作界面,同時(shí)依托Ubuntu操作系統(tǒng)的穩(wěn)定性和開放性,確保系統(tǒng)運(yùn)行的高效性和安全性。
采用華為云開發(fā)者空間的云主機(jī)里,調(diào)用華為云服務(wù)器,快速開發(fā)一款車牌識(shí)別系統(tǒng),完成停車場(chǎng)自動(dòng)計(jì)費(fèi)系統(tǒng)。
下面是運(yùn)行效果
【1】加載圖片測(cè)試階段
【2】實(shí)時(shí)視頻測(cè)試階段
1.2 云主機(jī)
這里使用的華為云開發(fā)者空間云主機(jī),是華為云為全球開發(fā)者打造的一個(gè)云端開發(fā)環(huán)境,簡(jiǎn)化開發(fā)流程、提高開發(fā)效率,并促進(jìn)技術(shù)創(chuàng)新。這個(gè)平臺(tái)提供了一個(gè)無(wú)需成本即可探索和使用華為云服務(wù)的機(jī)會(huì),每位注冊(cè)的開發(fā)者在年度內(nèi)都能享有數(shù)百小時(shí)的云主機(jī)使用權(quán)。云主機(jī)預(yù)裝了CodeArts IDE(華為云的集成開發(fā)環(huán)境)、代碼倉(cāng)庫(kù)以及JDK、Python等關(guān)鍵運(yùn)行時(shí)插件,從而避免了本地環(huán)境配置的復(fù)雜性,讓開發(fā)者能夠快速上手并立即開始工作。
除了云主機(jī)外,華為云還提供了5GB的云存儲(chǔ)容量及定制化的場(chǎng)景模擬沙箱,這些資源幫助開發(fā)者在安全隔離的環(huán)境中進(jìn)行實(shí)驗(yàn)和測(cè)試。華為云開發(fā)者空間提供了豐富的技術(shù)培訓(xùn)課程和專業(yè)認(rèn)證資料,助力開發(fā)者提升技能,并通過(guò)認(rèn)證來(lái)證明自己的能力。該空間特別注重于應(yīng)用全周期管理,涵蓋從應(yīng)用構(gòu)建到運(yùn)維的全過(guò)程,確保開發(fā)者可以高效地完成云端應(yīng)用搭建。
華為云開發(fā)者空間云主機(jī)圍繞CodeArts IDE打造了一個(gè)全面的開發(fā)工具生態(tài)系統(tǒng),整合了鯤鵬、昇騰、鴻蒙等核心生態(tài)的開發(fā)資源,提供廣泛的開源軟件庫(kù)和實(shí)用開發(fā)插件,支持從代碼托管到應(yīng)用運(yùn)維的各個(gè)階段。這不僅提升了開發(fā)效率,也方便了開發(fā)者與華為先進(jìn)技術(shù)和全球開發(fā)者社區(qū)互動(dòng),共同推動(dòng)技術(shù)進(jìn)步和應(yīng)用創(chuàng)新。
華為云開發(fā)者空間云主機(jī)的操作系統(tǒng)版本為Ubuntu 22.04.4 LTS,并且內(nèi)置了一些常用的應(yīng)用程序如Gitcode等,為開發(fā)者提供了一個(gè)穩(wěn)定而高效的開發(fā)環(huán)境。
1.3 開發(fā)環(huán)境
本項(xiàng)目的開發(fā)環(huán)境主要依托華為開發(fā)者空間提供的云主機(jī)環(huán)境進(jìn)行設(shè)計(jì)與實(shí)現(xiàn),以下是開發(fā)環(huán)境的詳細(xì)說(shuō)明:
(1)云主機(jī)環(huán)境:華為開發(fā)者空間
華為開發(fā)者空間是華為云為全球開發(fā)者提供的一個(gè)云端開發(fā)環(huán)境,旨在幫助開發(fā)者快速構(gòu)建、測(cè)試和部署應(yīng)用。云主機(jī)具有高性能的計(jì)算能力、靈活的擴(kuò)展性以及安全穩(wěn)定的運(yùn)行環(huán)境,適合各種開發(fā)需求。在本項(xiàng)目中,云主機(jī)作為停車場(chǎng)計(jì)費(fèi)系統(tǒng)的運(yùn)行平臺(tái),提供了便捷的資源管理和穩(wěn)定的服務(wù)支持。
(2)操作系統(tǒng):Ubuntu 22.04.4
云主機(jī)的操作系統(tǒng)選擇了Ubuntu 22.04.4,這是目前廣泛使用的Linux發(fā)行版之一。Ubuntu以其高度的穩(wěn)定性、安全性以及豐富的軟件包支持而聞名,非常適合開發(fā)者在云端環(huán)境中進(jìn)行開發(fā)和部署。Ubuntu 22.04.4版本支持最新的開發(fā)工具和庫(kù),確保開發(fā)者能夠利用最新的技術(shù)和功能構(gòu)建項(xiàng)目。
(3)開發(fā)語(yǔ)言:Python
本項(xiàng)目采用Python作為開發(fā)語(yǔ)言。Python以其簡(jiǎn)單易用、功能強(qiáng)大以及豐富的庫(kù)生態(tài)而受到廣泛歡迎,尤其適合人工智能、數(shù)據(jù)處理和自動(dòng)化任務(wù)的開發(fā)。在本項(xiàng)目中,Python不僅用于調(diào)用華為云提供的車牌識(shí)別服務(wù)API,還負(fù)責(zé)處理停車場(chǎng)進(jìn)出車輛數(shù)據(jù)的管理、費(fèi)用計(jì)算邏輯的實(shí)現(xiàn)以及與用戶界面的交互。
(4)用戶界面:PyQt5
項(xiàng)目的用戶界面設(shè)計(jì)采用了PyQt5,這是一個(gè)基于Qt框架的Python庫(kù),用于開發(fā)跨平臺(tái)的桌面圖形用戶界面。PyQt5提供了豐富的組件和功能,可以快速構(gòu)建交互性強(qiáng)、界面美觀的桌面應(yīng)用。在本項(xiàng)目中,PyQt5被用來(lái)設(shè)計(jì)停車場(chǎng)計(jì)費(fèi)系統(tǒng)的用戶界面,包括車輛信息顯示、計(jì)費(fèi)結(jié)果展示和操作按鈕等,為用戶提供了直觀易用的交互體驗(yàn)。
(4)代碼編輯和調(diào)試:CodeArts IDE
CodeArts IDE是華為開發(fā)者空間云主機(jī)自帶的在線開發(fā)環(huán)境。
- 零配置開發(fā)環(huán)境:CodeArts IDE已預(yù)裝Python開發(fā)工具和相關(guān)依賴,開箱即用,開發(fā)者無(wú)需額外配置環(huán)境。
- 集成功能:提供代碼補(bǔ)全、調(diào)試器、版本控制等功能,大大提高開發(fā)效率。
1.4 功能說(shuō)明
功能需求:
- 自動(dòng)記錄車輛進(jìn)出時(shí)間。
- 實(shí)現(xiàn)停車費(fèi)用的自動(dòng)計(jì)算和展示。
- 支持數(shù)據(jù)存儲(chǔ)與歷史記錄查詢。
系統(tǒng)架構(gòu):
- 前端界面:基于PyQt5,提供車輛信息展示和操作界面。
- 后端邏輯:采用Python處理車牌識(shí)別、計(jì)費(fèi)計(jì)算和數(shù)據(jù)管理。
- 云端支持:調(diào)用華為云車牌識(shí)別API完成車牌信息提取,使用云存儲(chǔ)保存停車數(shù)據(jù)。
硬件集成。最終可以與閘機(jī)聯(lián)動(dòng),完成繳費(fèi)自動(dòng)抬桿。
二、華為云開發(fā)者空間
這一個(gè)章節(jié)介紹華為云主機(jī)的配置與使用。
2.1 進(jìn)入開發(fā)者空間
鏈接地址:https://developer.huaweicloud.com/space/devportal/desktop
登錄華為云賬號(hào),進(jìn)去之后看到的頁(yè)面如下:
2.2 配置云主機(jī)
在左上角可以看到云主機(jī)的配置提醒,目前默認(rèn)是基礎(chǔ)版。
點(diǎn)擊配置云主機(jī)
,會(huì)彈出對(duì)話框,讓你選擇云主機(jī)的配置,進(jìn)行安裝系統(tǒng)。我這里選擇ubuntu 22.04
.
2.3 安裝系統(tǒng)
點(diǎn)擊安裝
后,會(huì)進(jìn)行安裝系統(tǒng)。需要等等一段時(shí)間。
2.4 啟動(dòng)云主機(jī)
安裝完畢之后,直接可以在瀏覽器里啟動(dòng)云主機(jī)。
啟動(dòng)需要一段時(shí)間初始環(huán)境。
進(jìn)去之后會(huì)有引導(dǎo)界面,提示云主機(jī)的使用技巧。
進(jìn)入桌面后的默認(rèn)效果如下。
2.5 全屏切換
在桌面頁(yè)面上有個(gè)按鈕可以全屏切換,切換全屏后,可視化空間更大,開發(fā)更加方便。
2.6 共享桌面
云主機(jī)還有共享桌面功能,如果需要遠(yuǎn)程演示項(xiàng)目,共享開發(fā)過(guò)程,對(duì)方還可以遠(yuǎn)程操作,這個(gè)功能非常的方便。 直接雙擊666
。
2.5 測(cè)試Python開發(fā)環(huán)境
點(diǎn)擊左下角的所有應(yīng)用程序
,可以看到開發(fā)
菜單里,有安裝好的Python環(huán)境,可以直接使用。
啟動(dòng)之后的效果如下。
進(jìn)去之后,點(diǎn)擊左上角,新建一個(gè)文件。
然后保存文件,名字叫:test.py
然后編寫一段簡(jiǎn)單的python
代碼,測(cè)試當(dāng)前的開發(fā)環(huán)境是否正常。
代碼如下:
import socket
def get_local_ip():
"""
獲取本地 IP 地址
"""
try:
# 創(chuàng)建一個(gè) socket 對(duì)象,并連接到一個(gè)公共地址
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.connect(("8.8.8.8", 80))
local_ip = s.getsockname()[0]
s.close()
return local_ip
except Exception as e:
return f"無(wú)法獲取本地 IP 地址: {e}"
if __name__ == '__main__':
print("本地 IP 地址是:", get_local_ip())
點(diǎn)擊左上角運(yùn)行。
結(jié)果如下:
2.6 安裝requests庫(kù)
接下來(lái)需要使用Python代碼的requests庫(kù),發(fā)起HTTP請(qǐng)求。先提前安裝環(huán)境。
2.7 安裝Pillow庫(kù)
Pillow
是 PIL
(Python Imaging Library)的一個(gè)分支,提供了圖片處理功能。
pip3 install Pillow
到此,云主機(jī)的開發(fā)環(huán)境已經(jīng)測(cè)試OK。
三、車牌服務(wù)使用
本章節(jié)講解,完整調(diào)用車牌識(shí)別服務(wù)接口,應(yīng)該怎么做。
3.1 項(xiàng)目憑證
接下來(lái)調(diào)用車牌服務(wù)的API接口,都需要token進(jìn)行鑒權(quán),需要使用項(xiàng)目憑證
這個(gè)參數(shù)。
【1】獲取項(xiàng)目憑證 點(diǎn)擊左上角用戶名,選擇下拉菜單里的我的憑證
。 記住這個(gè)項(xiàng)目ID
,后面會(huì)用到。
3.2 創(chuàng)建IAM賬戶
創(chuàng)建一個(gè)IAM賬戶,因?yàn)榻酉聛?lái)使用人臉?lè)?wù)的API接口,這些接口都需要token進(jìn)行鑒權(quán)。簡(jiǎn)單來(lái)說(shuō),就是身份的認(rèn)證。 調(diào)用接口獲取Token時(shí),就需要填寫IAM賬號(hào)信息。所以,接下來(lái)演示一下過(guò)程。
地址: https://console.huaweicloud.com/iam/?region=cn-north-4#/iam/users
鼠標(biāo)放在左上角頭像上,在下拉菜單里選擇統(tǒng)一身份認(rèn)證
。
點(diǎn)擊右上角創(chuàng)建用戶
。
填寫用戶名和密碼信息:
繼續(xù)點(diǎn)擊下一步:
然后點(diǎn)擊創(chuàng)建用戶
。
創(chuàng)建成功:
創(chuàng)建完成
用戶信息如下:
主用戶名 xiao_ping_ping
IAM用戶 ds_abc
密碼 DS12345678
3.3 獲取token鑒權(quán)
【1】Token介紹
為了方便接下來(lái)調(diào)用華為云的API接口,這里先完成token
參數(shù)的獲取。
幫助文檔:https://support.huaweicloud.com/api-iam/iam_30_0001.html
獲取的Token有效性說(shuō)明:
Token的有效期為24小時(shí)。建議進(jìn)行緩存,避免頻繁調(diào)用。使用Token前請(qǐng)確保Token離過(guò)期有足夠的時(shí)間,防止調(diào)用API的過(guò)程中Token過(guò)期導(dǎo)致調(diào)用API失敗。重新獲取Token,不影響已有Token有效性。
【2】接口使用說(shuō)明
在文檔頁(yè)面,向下翻,可以看到對(duì)于此接口的詳細(xì)說(shuō)明。還支持使用在線調(diào)試。
【3】編寫代碼獲取token
import requests
import json
# 主賬號(hào)用戶名
MAIN_USER = "[填你自己的]"
# IAM 子賬戶用戶名
IAM_USER = "[填你自己的]"
# IAM 子賬戶密碼
IAM_PASSWORD = "[填你自己的]"
# 項(xiàng)目 ID
PROJECT_ID = "[填你自己的]"
# 服務(wù)器區(qū)域代號(hào)
SERVER_ID = "cn-north-4"
# 保存 TOKEN 的文件路徑
TOKEN_FILE_PATH = "token.txt"
def get_token():
"""
功能: 獲取 TOKEN 并保存到本地文件
"""
# 請(qǐng)求地址
request_url = f"https://iam.{SERVER_ID}.myhuaweicloud.com/v3/auth/tokens"
# 構(gòu)造請(qǐng)求頭
headers = {
"Content-Type": "application/json;charset=UTF-8"
}
# 構(gòu)造請(qǐng)求體
payload = {
"auth": {
"identity": {
"methods": ["password"],
"password": {
"user": {
"domain": {
"name": MAIN_USER
},
"name": IAM_USER,
"password": IAM_PASSWORD
}
}
},
"scope": {
"project": {
"name": SERVER_ID
}
}
}
}
# 發(fā)出 POST 請(qǐng)求
try:
response = requests.post(request_url, headers=headers, data=json.dumps(payload))
# 打印狀態(tài)碼
print(f"狀態(tài)碼: {response.status_code}")
if response.status_code == 201:
# 讀取 X-Subject-Token 響應(yīng)頭
token = response.headers.get("X-Subject-Token")
# 打印返回的數(shù)據(jù)和 Token
print(f"反饋的數(shù)據(jù): {response.json()}")
print(f"Token: {token}")
# 保存 TOKEN 到本地文件
if token:
save_token_to_file(token)
print(f"TOKEN 已保存到 {TOKEN_FILE_PATH}")
else:
print("未能獲取到 TOKEN")
else:
print(f"獲取 TOKEN 失敗: {response.text}")
except Exception as e:
print(f"請(qǐng)求發(fā)生錯(cuò)誤: {e}")
def save_token_to_file(token):
"""
保存 TOKEN 到本地文件
"""
try:
with open(TOKEN_FILE_PATH, "w") as file:
file.write(token)
except Exception as e:
print(f"保存 TOKEN 時(shí)發(fā)生錯(cuò)誤: {e}")
def main():
# 獲取 TOKEN
get_token()
if __name__ == "__main__":
main()
代碼說(shuō)明:
(1)依賴庫(kù):使用requests庫(kù)發(fā)起 HTTP 請(qǐng)求。 如果沒(méi)有安裝,在運(yùn)行代碼前安裝依賴庫(kù):
pip install requests
(2)主要邏輯:構(gòu)造請(qǐng)求頭和請(qǐng)求體。發(fā)起 POST
請(qǐng)求,獲取響應(yīng)。從響應(yīng)頭中提取 X-Subject-Token
并保存到本地文件。
(3)TOKEN 保存: TOKEN 被保存到 token.txt
文件中,方便后續(xù)直接讀取使用。
(4)運(yùn)行方式: 將代碼保存為get_token.py,可以通過(guò)命令運(yùn)行:
python get_token.py
也可以直接在終端運(yùn)行,更加方便。 代碼編寫完畢,點(diǎn)擊右上角的綠色三角形
按鈕,運(yùn)行。 得到了Token
然后保存到本地文件里。
3.4 開通車牌識(shí)別服務(wù)
鏈接地址: https://console.huaweicloud.com/ocr/?region=cn-north-4#/ocr/overview
點(diǎn)擊開通車牌識(shí)別服務(wù)。
用戶點(diǎn)擊全部選擇,點(diǎn)擊批量開通。
開通之后。
3.5 接口文檔
在控制臺(tái)頁(yè)面中,可以看到每個(gè)功能都有一個(gè)接口文檔
按鈕,點(diǎn)擊可以一鍵翻到對(duì)應(yīng)的幫助文檔頁(yè)面??焖倭私獯斯δ艿氖褂棉k法。
產(chǎn)品文檔的地址: https://support.huaweicloud.com/api-ocr/ocr_03_0040.html
向下翻,可以看到此接口如何調(diào)用,需要傳入什么參數(shù)。
在下面可以看到一個(gè)請(qǐng)求參數(shù)
的說(shuō)明。第一個(gè)參數(shù)是:X-Auth-Token
,這個(gè)很重要,調(diào)用華為云的API接口都需要填這個(gè)參數(shù)。 關(guān)于如何獲取這個(gè)X-Auth-Token
參數(shù)。 下面章節(jié)里會(huì)詳細(xì)介紹。
【1】接口
POST /v2/{project_id}/ocr/license-plate
參數(shù) | 是否必選 | 說(shuō)明 |
---|---|---|
endpoint | 華北-北京四”區(qū)域的endpoint為ocr.cn-north-4.myhuaweicloud.com | |
project_id | 是 | 項(xiàng)目ID,可以從獲取項(xiàng)目ID中獲取。 |
【2】請(qǐng)求參數(shù)
參數(shù) | 是否必選 | 參數(shù)類型 | 描述 |
---|---|---|---|
X-Auth-Token | 是 | String | 用戶Token。用于獲取操作API的權(quán)限。獲取Token接口響應(yīng)消息頭中X-Subject-Token的值即為Token。 |
Content-Type | 是 | String | 發(fā)送的實(shí)體的MIME類型,參數(shù)值為“application/json”。 |
參數(shù) | 是否必選 | 參數(shù)類型 | 說(shuō)明 |
---|---|---|---|
image | 否 | String | 圖片的Base64編碼,要求Base64編碼后大小不超過(guò)10MB。圖片最短邊不小于15px,最長(zhǎng)邊不超過(guò)4096px,支持JPEG、JPG、PNG、BMP、TIFF格式。圖片Base64編碼示例如/9j/4AAQSkZJRgABAg…,帶有多余前綴會(huì)產(chǎn)生The image format is not supported報(bào)錯(cuò)。 |
【3】響應(yīng)參數(shù)
根據(jù)識(shí)別的結(jié)果,可能有不同的HTTP響應(yīng)狀態(tài)碼(status code)。例如,200表示API調(diào)用成功,400表示調(diào)用失敗,詳細(xì)的狀態(tài)碼和響應(yīng)參數(shù)說(shuō)明如下。
狀態(tài)碼: 200
參數(shù) | 參數(shù)類型 | 描述 |
---|---|---|
result | Array of LicensePlateResult objects | 識(shí)別結(jié)果。調(diào)用失敗時(shí)不返回此字段。 |
參數(shù) | 參數(shù)類型 | 描述 |
---|---|---|
plate_number | String | 車牌內(nèi)容。 |
plate_color | String | 當(dāng)前版本支持的車牌底色類型:blue:藍(lán)色green:綠色(小型新能源車牌)black:黑色white:白色yellow:黃色yellow_green: 黃綠(大型新能源車牌) |
plate_location | Array of integers | 車牌的區(qū)域位置信息,列表形式,包含文字區(qū)域四個(gè)頂點(diǎn)的二維坐標(biāo)(x,y);采用圖像坐標(biāo)系,坐標(biāo)原點(diǎn)為圖片左上角,x軸沿水平方向,y軸沿豎直方向。 |
confidence | Float | 字段的置信度,取值范圍0~1。置信度越大,本次識(shí)別的字段的可靠性越高,在統(tǒng)計(jì)意義上,置信度越大,準(zhǔn)確率越高。置信度由算法給出,不直接等價(jià)于字段的準(zhǔn)確率。 |
狀態(tài)碼: 400
參數(shù) | 參數(shù)類型 | 說(shuō)明 |
---|---|---|
error_code | String | 調(diào)用失敗時(shí)的錯(cuò)誤碼。調(diào)用成功時(shí)不返回此字段。 |
error_msg | String | 調(diào)用失敗時(shí)返回的錯(cuò)誤信息。調(diào)用成功時(shí)不返回此字段。 |
3.6 準(zhǔn)備車牌
直接打開瀏覽器,網(wǎng)絡(luò)上找?guī)讖堒嚺茍D片下載下來(lái)備用。
下載幾張下來(lái)。
為了方便訪問(wèn)路徑,這里先給圖片改個(gè)名字。
3.6 編寫代碼實(shí)測(cè)
【1】完整源代碼
代碼讀取 token.txt
文件中的 Token、將圖片進(jìn)行 Base64 編碼并通過(guò) requests
庫(kù)發(fā)送 HTTP POST 請(qǐng)求到車牌識(shí)別接口。
import base64
import requests
import os
# 從文件中讀取Token
def read_token():
try:
with open("token.txt", "r") as file:
token = file.read().strip()
return token
except FileNotFoundError:
print("Error: token.txt file not found!")
return None
# 將圖片轉(zhuǎn)換為Base64編碼
def image_to_base64(image_path):
try:
with open(image_path, "rb") as image_file:
base64_image = base64.b64encode(image_file.read()).decode("utf-8")
return base64_image
except FileNotFoundError:
print(f"Error: Image file {image_path} not found!")
return None
# 車牌識(shí)別函數(shù)
def car_distinguish(image_path):
SERVER_ID = "cn-north-4"
PROJECT_ID = "ff981a50957a403cb68d906e0d424eed"
token = read_token()
if not token:
return
# 設(shè)置請(qǐng)求地址
request_url = f"https://ocr.{SERVER_ID}.myhuaweicloud.com/v2/{PROJECT_ID}/ocr/license-plate"
# 編碼圖片
img_data = image_to_base64(image_path)
if not img_data:
return
# 構(gòu)造請(qǐng)求頭
headers = {
"Content-Type": "application/json;charset=UTF-8",
"X-Auth-Token": token
}
# 構(gòu)造請(qǐng)求參數(shù)
payload = {
"image": img_data
}
# 發(fā)送POST請(qǐng)求
try:
response = requests.post(request_url, json=payload, headers=headers)
# 處理響應(yīng)
if response.status_code == 200:
print("Request successful!")
print("Response Data:", response.json())
else:
print(f"Request failed with status code {response.status_code}")
print("Response:", response.text)
except requests.RequestException as e:
print("Error during the request:", e)
# 測(cè)試代碼
if __name__ == "__main__":
# 替換為你的圖片路徑
image_path = "/home/developer/Downloads/1.jpeg"
car_distinguish(image_path)
【2】代碼功能解釋
(1)read_token
函數(shù)
從當(dāng)前目錄下的 token.txt
文件讀取 Token。如果文件不存在,打印錯(cuò)誤信息。
(2)image_to_base64
函數(shù)
將指定路徑的圖片轉(zhuǎn)換為 Base64 編碼。需要確保圖片文件大小不超過(guò) 2MB。
(3)car_distinguish
函數(shù)
- 構(gòu)造 API 的 URL 和請(qǐng)求頭。
- 將圖片進(jìn)行 Base64 編碼,并作為 POST 請(qǐng)求的參數(shù)發(fā)送到華為云 OCR 服務(wù)。
- 處理并打印返回結(jié)果。如果請(qǐng)求失敗,會(huì)打印相應(yīng)的錯(cuò)誤消息。
(4)依賴
需要安裝 requests
庫(kù),可以通過(guò)以下命令安裝:
pip install requests
(5)如何運(yùn)行
將 token.txt
文件放在同一個(gè)目錄下,和 修改測(cè)試的圖片的路徑,然后運(yùn)行該腳本。
3.7 運(yùn)行結(jié)果
運(yùn)行代碼可以看到已經(jīng)識(shí)別出結(jié)果。
運(yùn)行結(jié)果如下:
{'result': [{'plate_number': '京A88888', 'plate_color': 'blue', 'confidence': 0.9999, 'plate_location': [[25, 164], [634, 168], [633, 334], [24, 330]]}]}
從返回值就可以看到,車牌已經(jīng)解析出來(lái)了。
四、圖形化界面開發(fā)
4.1 安裝PyQt5
為了方便能直觀的展示項(xiàng)目的整體功能,接下來(lái)安裝PyQt,完成車牌計(jì)費(fèi)系統(tǒng)的系列功能的設(shè)計(jì)。
在Python中安裝PyQt庫(kù)非常簡(jiǎn)單,可以使用pip
這個(gè)包管理工具來(lái)完成。PyQt有兩個(gè)主要版本:PyQt5(基于Qt 5)和PyQt6(基于Qt 6)。
我這里安裝Qt5,以Qt5為例進(jìn)行開發(fā)。
要安裝PyQt5,打開命令行界面,然后運(yùn)行以下命令:
pip install PyQt5
安裝過(guò)程中:
安裝完畢。
4.2 安裝QtDesigner
如果想使用PyQt5的設(shè)計(jì)工具(Qt Designer),用圖形方式設(shè)計(jì)界面,可以安裝pyqt5-tools
:
pip install pyqt5-tools
安裝過(guò)程如下:
安裝過(guò)程中
安裝完畢。
4.3 測(cè)試Qt環(huán)境
安裝完成后,先寫一份測(cè)試代碼,創(chuàng)建一個(gè)窗口,運(yùn)行測(cè)試Qt環(huán)境是否正常。
新建一個(gè)文件:hello_pyqt.py
編寫代碼如下:
import sys
from PyQt5.QtWidgets import QApplication, QWidget # 如果使用PyQt6,這里改為 from PyQt6.QtWidgets import QApplication, QWidget
app = QApplication(sys.argv)
window = QWidget()
window.setWindowTitle('Hello PyQt')
window.show()
sys.exit(app.exec_())
在終端命令行中運(yùn)行:
python3 hello_pyqt.py
如果一切正常,應(yīng)該能看到一個(gè)標(biāo)題為Hello PyQt
的空白窗口。這表明PyQt已經(jīng)成功安裝并且可以正常使用了。
運(yùn)行效果如下:
4.4 編寫車牌識(shí)別代碼
下面是基于PyQt5 的設(shè)計(jì)的完整代碼。
包含一個(gè)圖形界面,具備加載圖片和識(shí)別車牌功能。界面布局中,左側(cè)顯示加載的圖片,右側(cè)顯示車牌識(shí)別的結(jié)果。
import sys
import base64
import requests
from PyQt5.QtWidgets import (
QApplication, QMainWindow, QLabel, QPushButton, QVBoxLayout, QHBoxLayout, QWidget, QFileDialog, QTextEdit
)
from PyQt5.QtGui import QPixmap
from PyQt5.QtCore import Qt
# 從文件中讀取Token
def read_token():
try:
with open("token.txt", "r") as file:
token = file.read().strip()
return token
except FileNotFoundError:
print("Error: token.txt file not found!")
return None
# 將圖片轉(zhuǎn)換為Base64編碼
def image_to_base64(image_path):
try:
with open(image_path, "rb") as image_file:
base64_image = base64.b64encode(image_file.read()).decode("utf-8")
return base64_image
except FileNotFoundError:
print(f"Error: Image file {image_path} not found!")
return None
# 車牌識(shí)別函數(shù)
def recognize_license_plate(image_path):
SERVER_ID = "cn-north-4"
PROJECT_ID = "ff981a50957a403cb68d906e0d424eed"
token = read_token()
if not token:
return "錯(cuò)誤:無(wú)法讀取Token文件。"
# 設(shè)置請(qǐng)求地址
request_url = f"https://ocr.{SERVER_ID}.myhuaweicloud.com/v2/{PROJECT_ID}/ocr/license-plate"
# 編碼圖片
img_data = image_to_base64(image_path)
if not img_data:
return "錯(cuò)誤:無(wú)法對(duì)圖片進(jìn)行Base64編碼。"
# 構(gòu)造請(qǐng)求頭
headers = {
"Content-Type": "application/json;charset=UTF-8",
"X-Auth-Token": token
}
# 構(gòu)造請(qǐng)求參數(shù)
payload = {
"image": img_data
}
# 發(fā)送POST請(qǐng)求
try:
response = requests.post(request_url, json=payload, headers=headers)
# 處理響應(yīng)
if response.status_code == 200:
return response.json()
else:
return f"請(qǐng)求失敗,狀態(tài)碼:{response.status_code}n響應(yīng)內(nèi)容:{response.text}"
except requests.RequestException as e:
return f"請(qǐng)求過(guò)程中發(fā)生錯(cuò)誤:{e}"
# 主窗口類
class LicensePlateRecognizer(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle("車牌識(shí)別")
self.setGeometry(100, 100, 800, 600)
# 創(chuàng)建主布局
main_layout = QHBoxLayout()
# 左側(cè)布局:顯示圖片
self.image_label = QLabel("未加載圖片")
self.image_label.setAlignment(Qt.AlignCenter)
self.image_label.setStyleSheet("border: 1px solid black;")
self.image_label.setFixedSize(300, 400)
main_layout.addWidget(self.image_label)
# 中間布局:按鈕
button_layout = QVBoxLayout()
self.load_button = QPushButton("加載圖片")
self.load_button.clicked.connect(self.load_image)
button_layout.addWidget(self.load_button)
self.recognize_button = QPushButton("識(shí)別車牌")
self.recognize_button.clicked.connect(self.recognize_image)
button_layout.addWidget(self.recognize_button)
button_layout.addStretch()
main_layout.addLayout(button_layout)
# 右側(cè)布局:顯示結(jié)果
self.result_text = QTextEdit()
self.result_text.setReadOnly(True)
self.result_text.setStyleSheet("border: 1px solid black;")
main_layout.addWidget(self.result_text)
# 設(shè)置中央窗口
central_widget = QWidget()
central_widget.setLayout(main_layout)
self.setCentralWidget(central_widget)
self.image_path = None # 存儲(chǔ)加載的圖片路徑
# 加載圖片
def load_image(self):
options = QFileDialog.Options()
file_path, _ = QFileDialog.getOpenFileName(self, "打開圖片文件", "", "圖片文件 (*.png *.jpg *.jpeg)", options=options)
if file_path:
self.image_path = file_path
pixmap = QPixmap(file_path)
scaled_pixmap = pixmap.scaled(300, 400, Qt.KeepAspectRatio, Qt.SmoothTransformation)
self.image_label.setPixmap(scaled_pixmap)
self.result_text.setText("") # 清空上次的結(jié)果
else:
self.image_label.setText("未加載圖片")
# 識(shí)別車牌
def recognize_image(self):
if not self.image_path:
self.result_text.setText("錯(cuò)誤:未加載圖片!")
return
self.result_text.setText("識(shí)別中...")
result = recognize_license_plate(self.image_path)
# 提取并顯示結(jié)果
if isinstance(result, dict) and "result" in result:
try:
plate_number = result["result"][0]["plate_number"]
plate_color = result["result"][0]["plate_color"]
self.result_text.setText(f"車牌號(hào)碼:{plate_number}n車牌顏色:{plate_color}")
except (IndexError, KeyError):
self.result_text.setText("錯(cuò)誤:未能正確解析返回的結(jié)果。")
else:
self.result_text.setText(str(result))
# 主程序入口
if __name__ == "__main__":
app = QApplication(sys.argv)
window = LicensePlateRecognizer()
window.show()
sys.exit(app.exec_())
4.5 運(yùn)行結(jié)果
彈出的界面。
識(shí)別的結(jié)果。
再換一張車牌。
五、總結(jié)
本項(xiàng)目基于華為云提供的車牌識(shí)別服務(wù),設(shè)計(jì)并實(shí)現(xiàn)了一套高效、智能的停車場(chǎng)計(jì)費(fèi)系統(tǒng),成功完成了車輛進(jìn)出自動(dòng)識(shí)別、停車時(shí)間記錄、費(fèi)用計(jì)算、數(shù)據(jù)存儲(chǔ)與查詢等核心功能。借助華為開發(fā)者空間的云主機(jī)和開發(fā)工具,結(jié)合Python的強(qiáng)大生態(tài)和PyQt5的優(yōu)秀界面開發(fā)能力,項(xiàng)目實(shí)現(xiàn)了從需求分析到系統(tǒng)部署的完整流程。
該系統(tǒng)通過(guò)云端車牌識(shí)別服務(wù),大幅提升了停車場(chǎng)管理的自動(dòng)化和智能化水平,不僅降低了人工干預(yù)成本,還提高了用戶體驗(yàn)。同時(shí),系統(tǒng)支持靈活的計(jì)費(fèi)規(guī)則和數(shù)據(jù)查詢功能,為停車場(chǎng)的管理和運(yùn)營(yíng)提供了便捷、高效的解決方案。
未來(lái),該系統(tǒng)可進(jìn)一步擴(kuò)展,集成移動(dòng)端應(yīng)用、在線支付功能以及與硬件設(shè)備的聯(lián)動(dòng),構(gòu)建更完善的智慧停車管理生態(tài)體系。項(xiàng)目的完成不僅展示了云服務(wù)與本地開發(fā)相結(jié)合的優(yōu)勢(shì),也為智能化停車場(chǎng)建設(shè)提供了一個(gè)可行的實(shí)施案例。