1. 項(xiàng)目介紹
車(chē)牌識(shí)別系統(tǒng)是計(jì)算機(jī)視頻圖像識(shí)別技術(shù)在車(chē)輛牌照識(shí)別中的一種經(jīng)典應(yīng)用,現(xiàn)在高速電子收費(fèi)(ETC),違規(guī)駕駛、超速駕駛、停車(chē)場(chǎng)自動(dòng)收費(fèi)系統(tǒng),等等很多場(chǎng)景都用到了車(chē)牌識(shí)別技術(shù)。
這篇文章就利用華為云的人工智能分類(lèi)里的車(chē)牌號(hào)識(shí)別接口,快速搭建一個(gè)停車(chē)場(chǎng)自動(dòng)收費(fèi)系統(tǒng),硬件采用樹(shù)莓派開(kāi)發(fā)板,攝像頭采用普通的免驅(qū)USB攝像頭,使用超聲波測(cè)距模塊檢測(cè)是否有車(chē)輛靠近,車(chē)牌識(shí)別接口采用的是在線的方式;軟件后臺(tái)、UI界面采用QT、C++設(shè)計(jì),支持跨平臺(tái),比較方便,代碼一次寫(xiě)完,主流平臺(tái)都可以編譯運(yùn)行。
本項(xiàng)目只是為了演示車(chē)牌號(hào)識(shí)別接口的使用,快速搭建了一個(gè)應(yīng)用場(chǎng)景,很多細(xì)節(jié)還沒(méi)考慮完善。
識(shí)別思路: 使用兩個(gè)USB攝像頭當(dāng)做進(jìn)口與出口,分別使用超聲波測(cè)距模塊不斷測(cè)量攝像頭前方的物體距離,當(dāng)檢測(cè)到車(chē)輛靠近的時(shí)候,讀取當(dāng)前攝像頭的一幀數(shù)據(jù),通過(guò)華為云的車(chē)牌號(hào)識(shí)別接口進(jìn)行識(shí)別,返回識(shí)別結(jié)果;如果是入口攝像頭,那么就將識(shí)別的車(chē)牌存放到數(shù)據(jù)庫(kù),并記錄當(dāng)前入場(chǎng)時(shí)間,如果是出口,就與當(dāng)前數(shù)據(jù)庫(kù)里的車(chē)牌數(shù)據(jù)進(jìn)行對(duì)比,找到車(chē)牌入場(chǎng)的時(shí)間,與當(dāng)前時(shí)間進(jìn)行相減得到停車(chē)時(shí)間,再根據(jù)停車(chē)場(chǎng)設(shè)置的計(jì)費(fèi)規(guī)則,完成費(fèi)用提示,語(yǔ)音播報(bào),告訴車(chē)主需要付款多少錢(qián)。
2. 配置華為云接口
2.1 開(kāi)通車(chē)牌識(shí)別服務(wù)
當(dāng)前體驗(yàn)的是在線API車(chē)牌接口,需要先開(kāi)通車(chē)牌識(shí)別服務(wù),才可以使用接口(需要先注冊(cè)華為云賬號(hào)登錄)。
車(chē)牌識(shí)別服務(wù)開(kāi)通地址: https://console.huaweicloud.com/ocr/?region=cn-north-4#/ocr/overview
接口的使用計(jì)費(fèi)說(shuō)明頁(yè)面: https://www.huaweicloud.com/pricing.html?tab=detail#/ocr
可以看到,如果使用在線API接口實(shí)現(xiàn)車(chē)牌識(shí)別,每月免費(fèi)1000次,作為體驗(yàn)來(lái)講已經(jīng)足夠了。
2.2 車(chē)牌識(shí)別接口使用介紹
在線文檔地址: https://support.huaweicloud.com/api-ocr/ocr_03_0040.html
在這個(gè)頁(yè)面可以看到在線請(qǐng)求的接口地址,參數(shù)、響應(yīng)結(jié)果等詳細(xì)介紹。
如果想快速體驗(yàn)效果,可以直接使用在線調(diào)試功能,這個(gè)功能非常好用,可以快速體驗(yàn)各種接口,參數(shù)的功能。
在線調(diào)試地址: https://apiexplorer.developer.huaweicloud.com/apiexplorer/doc?product=OCR&api=RecognizeLicensePlate
準(zhǔn)備一張待測(cè)試識(shí)別的車(chē)牌:
使用接口調(diào)試:
調(diào)試的時(shí)候需要填入圖片的base64編碼,可以直接使用瀏覽器自帶的功能實(shí)現(xiàn)。
官網(wǎng)文檔: https://support.huaweicloud.com/ocr_faq/ocr_01_0032.html
實(shí)操:
2.3 接口總結(jié)
請(qǐng)求方式: post
?
URL地址格式: POST https://{endpoint}/v2/{project_id}/ocr/license-plate
?
實(shí)際地址: (下面填的是我的項(xiàng)目ID,需要替換成自己,服務(wù)器域名也是一樣)
https://ocr.cn-north-4.myhuaweicloud.com/v2/0e5957be8a00f53c2fa7c0045e4d8fbf/ocr/license-plate
?
請(qǐng)求頭:
{
"User-Agent": "API Explorer",
"X-Auth-Token": "******", 這里填Token
"Content-Type": "application/json;charset=UTF-8"
}
?
?
請(qǐng)求體:
{
"image": "/9j/4AAQSkZJRgABAQEAkACQAAD/2wBDAAMCAgMCAgMDAwME.........這里是圖片的base64編碼,非常長(zhǎng),這里就省略了,明白意思就行....."
}
?
響應(yīng)頭:
{
"Darklaunch-Rule-Name": "s-bdc8-1254-202112061537",
"Server": "api-gateway",
"X-Request-Id": "6b9a88702fe419acd8b638d35a9bf523",
"Connection": "keep-alive",
"X-ModelArts-Trace": "6b9a88702fe419acd8b638d35a9bf523",
"Content-Length": "544",
"X-ModelArts-Latency": "100",
"Date": "Sun, 26 Dec 2021 15:29:46 GMT",
"Instance-Request-Count": "1",
"Content-Type": "application/json"
}
?
響應(yīng)體:
{
"result": [
{
"plate_number": "京A33333",
"plate_color": "blue",
"plate_location": [
[
236,
331
],
[
882,
331
],
[
882,
542
],
[
236,
542
]
],
"confidence": 0.9964
}
]
}
2.4 接口參數(shù)解釋
上面2.3小節(jié)里總結(jié)了接口地址一些詳細(xì)參數(shù),這里把接口里的一些重要參數(shù)解釋一遍。
車(chē)牌識(shí)別的URL:
POST https://{endpoint}/v2/{project_id}/ocr/license-plate
endpoint 是指定承載REST服務(wù)端點(diǎn)的服務(wù)器域名或IP,不同服務(wù)不同區(qū)域的endpoint不同,可以從終端節(jié)點(diǎn)中獲取。
例如,OCR服務(wù)在“華北-北京四”區(qū)域的 “endpoint” 為“ocr.cn-north-4.myhuaweicloud.com”。
URL里還有一個(gè)project_id
參數(shù),這是項(xiàng)目ID,可以從獲取項(xiàng)目ID中獲取。
請(qǐng)求頭里有個(gè)比較總要的參數(shù):X-Auth-Token
, 華為云上面幾乎所有的API接口請(qǐng)求頭都需要填X-Auth-Token
,獲取的方法在這里: https://bbs.huaweicloud.com/blogs/317759 翻到第3小節(jié)。
3. 項(xiàng)目實(shí)現(xiàn)代碼
3.1 車(chē)牌識(shí)別請(qǐng)求代碼
//車(chē)牌識(shí)別接口
void Widget::car_distinguish(QImage imag)
{
function_select=0;
QString requestUrl;
QNetworkRequest request;
?
//存放圖片BASE64編碼
QString imgData;
?
//設(shè)置請(qǐng)求地址
QUrl url;
?
//車(chē)牌識(shí)別請(qǐng)求地址
requestUrl = QString("https://ocr.%1.myhuaweicloud.com/v2/%2/ocr/license-plate")
.arg(SERVER_ID)
.arg(PROJECT_ID);
?
//設(shè)置數(shù)據(jù)提交格式
request.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("application/json;charset=UTF-8"));
?
//將圖片進(jìn)行Base64編碼
imgData = QString(toBase64(imag)); //編碼后的圖片大小不超過(guò)2M
//設(shè)置token
request.setRawHeader("X-Auth-Token",Token);
?
//構(gòu)造請(qǐng)求
url.setUrl(requestUrl);
request.setUrl(url);
?
QString post_param=QString("{"image": "%1"}").arg(imgData);
?
//發(fā)送請(qǐng)求
manager- >post(request, post_param.toUtf8());
}
3.2 圖片base64編碼
/*
將圖片進(jìn)行base64編碼
*/
QByteArray Widget::toBase64(const QImage &image)
{
//將要檢測(cè)的圖片進(jìn)行BASE64編碼
QByteArray ba;
QBuffer buffer(&ba);
buffer.open(QIODevice::WriteOnly);
//以png格式將圖片數(shù)據(jù)寫(xiě)入ba
image.save(&buffer,"jpg");
?
buffer.close();
return ba.toBase64();
}
3.3 超聲波模塊驅(qū)動(dòng)代碼
#include < linux/kernel.h >
#include < linux/module.h >
#include < linux/miscdevice.h >
#include < linux/fs.h >
#include < linux/uaccess.h >
#include < linux/io.h >
#include < linux/irq.h >
#include < linux/delay.h >
#include < linux/workqueue.h >
#include < linux/gpio.h >
#include < mach/gpio.h >
#include < plat/gpio-cfg.h >
#include < linux/timer.h >
#include < linux/wait.h >
#include < linux/sched.h >
#include < linux/poll.h >
#include < linux/fcntl.h >
#include < linux/interrupt.h >
#include < linux/ktime.h >
?
static unsigned int distance_irq; /*存放中斷號(hào)*/
static u32 *GPB_DAT=NULL;
static u32 *GPB_CON=NULL;
?
/*
工作隊(duì)列處理函數(shù):
*/
static void distance_work_func(struct work_struct *work)
{
u32 time1,time2;
time1=ktime_to_us(ktime_get()); /*獲取當(dāng)前時(shí)間,再轉(zhuǎn)換為 us 單位*/
?
/*等待高電平時(shí)間結(jié)束*/
while(gpio_get_value(EXYNOS4_GPX1(0))){}
time2=ktime_to_us(ktime_get()); /*獲取當(dāng)前時(shí)間,再轉(zhuǎn)換為 us 單位*/
?
printk("us=%dn",time2-time1); /*us/58=厘米*/
}
?
/*靜態(tài)方式初始化工作隊(duì)列*/
static DECLARE_WORK(distance_work,distance_work_func);
?
/*
中斷處理函數(shù): 用于檢測(cè)超聲波測(cè)距的回波
*/
static irqreturn_t distance_handler(int irq, void *dev)
{
/*調(diào)度工作隊(duì)列*/
schedule_work(&distance_work);
return IRQ_HANDLED;
}
?
static void distance_function(unsigned long data);
/*靜態(tài)方式定義內(nèi)核定時(shí)器*/
static DEFINE_TIMER(distance_timer,distance_function,0,0);
?
/*內(nèi)核定時(shí)器超時(shí)處理函數(shù): 觸發(fā)超聲波發(fā)送方波*/
static void distance_function(unsigned long data)
{
static u8 state=0;
state=!state;
/*更改GPIO口電平*/
if(state)
{
*GPB_DAT|=1< 7;
}
else
{
*GPB_DAT&=~(1< 7);
}
/*修改定時(shí)器的超時(shí)時(shí)間*/
mod_timer(&distance_timer,jiffies+msecs_to_jiffies(100));
}
?
static int __init tiny4412_distance_dev_init(void)
{
int err;
/*1. 映射GPIO口地址*/
GPB_DAT=ioremap(0x11400044,4);
GPB_CON=ioremap(0x11400040,4);
?
*GPB_CON&=~(0xF< 4*7);
*GPB_CON|=0x1< 4*7; /*配置輸出模式*/
/*2. 根據(jù)GPIO口編號(hào),獲取中斷號(hào)*/
distance_irq=gpio_to_irq(EXYNOS4_GPX1(0));
/*3. 注冊(cè)中斷*/
err=request_irq(distance_irq,distance_handler,IRQ_TYPE_EDGE_RISING,"distance_device",NULL);
if(err!=0)printk("中斷注冊(cè)失敗!n");
else printk("中斷:超聲波測(cè)距驅(qū)動(dòng)安裝成功!n");
?
/*4. 修改定時(shí)器超時(shí)時(shí)間*/
mod_timer(&distance_timer,jiffies+msecs_to_jiffies(100));
return 0;
}
?
static void __exit tiny4412_distance_dev_exit(void)
{
/*5. 注銷(xiāo)中斷*/
free_irq(distance_irq,NULL);
?
/*6. 停止定時(shí)器*/
del_timer(&distance_timer);
/*7. 取消IO映射*/
iounmap(GPB_DAT);
iounmap(GPB_CON);
printk("中斷:超聲波測(cè)距驅(qū)動(dòng)卸載成功!n");
}
?
module_init(tiny4412_distance_dev_init);
module_exit(tiny4412_distance_dev_exit);
MODULE_LICENSE("GPL");
審核編輯:湯梓紅
-
usb
+關(guān)注
關(guān)注
60文章
7945瀏覽量
264627 -
攝像頭
+關(guān)注
關(guān)注
60文章
4841瀏覽量
95690 -
樹(shù)莓派
+關(guān)注
關(guān)注
116文章
1707瀏覽量
105629 -
華為云
+關(guān)注
關(guān)注
3文章
2491瀏覽量
17425
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論