1. 專案介紹
車牌識別系統是計算機視頻影像識別技術在車輛牌照識別中的一種經典應用,現在高速電子收費(ETC),違規駕駛、超速駕駛、停車場自動收費系統,等等很多場景都用到了車牌識別技術,
這篇文章就利用華為云的人工智能分類里的車牌號識別介面,快速搭建一個停車場自動收費系統,硬體采用樹莓派開發板,攝像頭采用普通的免驅USB攝像頭,使用超聲波測距模塊檢測是否有車輛靠近,車牌識別介面采用的是在線的方式;軟體后臺、UI界面采用QT、C++設計,支持跨平臺,比較方便,代碼一次寫完,主流平臺都可以編譯運行,
本專案只是為了演示車牌號識別介面的使用,快速搭建了一個應用場景,很多細節還沒考慮完善,
識別思路: 使用兩個USB攝像頭當做進口與出口,分別使用超聲波測距模塊不斷測量攝像頭前方的物體距離,當檢測到車輛靠近的時候,讀取當前攝像頭的一幀資料,通過華為云的車牌號識別介面進行識別,回傳識別結果;如果是入口攝像頭,那么就將識別的車牌存放到資料庫,并記錄當前入場時間,如果是出口,就與當前資料庫里的車牌資料進行對比,找到車牌入場的時間,與當前時間進行相減得到停車時間,再根據停車場設定的計費規則,完成費用提示,語音播報,告訴車主需要付款多少錢,




2. 配置華為云介面
2.1 開通車牌識別服務
當前體驗的是在線API車牌介面,需要先開通車牌識別服務,才可以使用介面(需要先注冊華為云賬號登錄),
車牌識別服務開通地址: https://console.huaweicloud.com/ocr/?region=cn-north-4#/ocr/overview

介面的使用計費說明頁面: https://www.huaweicloud.com/pricing.html?tab=detail#/ocr

可以看到,如果使用在線API介面實作車牌識別,每月免費1000次,作為體驗來講已經足夠了,
2.2 車牌識別介面使用介紹
在線檔案地址: https://support.huaweicloud.com/api-ocr/ocr_03_0040.html
在這個頁面可以看到在線請求的介面地址,引數、回應結果等詳細介紹,

如果想快速體驗效果,可以直接使用在線除錯功能,這個功能非常好用,可以快速體驗各種介面,引數的功能,
在線除錯地址: https://apiexplorer.developer.huaweicloud.com/apiexplorer/doc?product=OCR&api=RecognizeLicensePlate
準備一張待測驗識別的車牌:

使用介面除錯:

除錯的時候需要填入圖片的base64編碼,可以直接使用瀏覽器自帶的功能實作,
官網檔案: https://support.huaweicloud.com/ocr_faq/ocr_01_0032.html

實操:

2.3 介面總結
請求方式: post
URL地址格式: POST https://{endpoint}/v2/{project_id}/ocr/license-plate
實際地址: (下面填的是我的專案ID,需要替換成自己,服務器域名也是一樣)
https://ocr.cn-north-4.myhuaweicloud.com/v2/0e5957be8a00f53c2fa7c0045e4d8fbf/ocr/license-plate
請求頭:
{
"User-Agent": "API Explorer",
"X-Auth-Token": "******", 這里填Token
"Content-Type": "application/json;charset=UTF-8"
}
請求體:
{
"image": "/9j/4AAQSkZJRgABAQEAkACQAAD/2wBDAAMCAgMCAgMDAwME.........這里是圖片的base64編碼,非常長,這里就省略了,明白意思就行....."
}
回應頭:
{
"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"
}
回應體:
{
"result": [
{
"plate_number": "京A33333",
"plate_color": "blue",
"plate_location": [
[
236,
331
],
[
882,
331
],
[
882,
542
],
[
236,
542
]
],
"confidence": 0.9964
}
]
}
2.4 介面引數解釋
上面2.3小節里總結了介面地址一些詳細引數,這里把介面里的一些重要引數解釋一遍,
車牌識別的URL:
POST https://{endpoint}/v2/{project_id}/ocr/license-plate
endpoint 是指定承載REST服務端點的服務器域名或IP,不同服務不同區域的endpoint不同,可以從終端節點中獲取,
例如,OCR服務在“華北-北京四”區域的**“endpoint”**為“ocr.cn-north-4.myhuaweicloud.com”,

URL里還有一個project_id引數,這是專案ID,可以從獲取專案ID中獲取,

請求頭里有個比較總要的引數: X-Auth-Token, 華為云上面幾乎所有的API介面請求頭都需要填X-Auth-Token,獲取的方法在這里: https://bbs.huaweicloud.com/blogs/317759 翻到第3小節,

3. 專案實作代碼
3.1 車牌識別請求代碼
//車牌識別介面
void Widget::car_distinguish(QImage imag)
{
function_select=0;
QString requestUrl;
QNetworkRequest request;
//存放圖片BASE64編碼
QString imgData;
//設定請求地址
QUrl url;
//車牌識別請求地址
requestUrl = QString("https://ocr.%1.myhuaweicloud.com/v2/%2/ocr/license-plate")
.arg(SERVER_ID)
.arg(PROJECT_ID);
//設定資料提交格式
request.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("application/json;charset=UTF-8"));
//將圖片進行Base64編碼
imgData = QString(toBase64(imag)); //編碼后的圖片大小不超過2M
//設定token
request.setRawHeader("X-Auth-Token",Token);
//構造請求
url.setUrl(requestUrl);
request.setUrl(url);
QString post_param=QString("{\"image\": \"%1\"}").arg(imgData);
//發送請求
manager->post(request, post_param.toUtf8());
}
3.2 圖片base64編碼
/*
將圖片進行base64編碼
*/
QByteArray Widget::toBase64(const QImage &image)
{
//將要檢測的圖片進行BASE64編碼
QByteArray ba;
QBuffer buffer(&ba);
buffer.open(QIODevice::WriteOnly);
//以png格式將圖片資料寫入ba
image.save(&buffer,"jpg");
buffer.close();
return ba.toBase64();
}
3.3 超聲波模塊驅動代碼
#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; /*存放中斷號*/
static u32 *GPB_DAT=NULL;
static u32 *GPB_CON=NULL;
/*
作業佇列處理函式:
*/
static void distance_work_func(struct work_struct *work)
{
u32 time1,time2;
time1=ktime_to_us(ktime_get()); /*獲取當前時間,再轉換為 us 單位*/
/*等待高電平時間結束*/
while(gpio_get_value(EXYNOS4_GPX1(0))){}
time2=ktime_to_us(ktime_get()); /*獲取當前時間,再轉換為 us 單位*/
printk("us=%d\n",time2-time1); /*us/58=厘米*/
}
/*靜態方式初始化作業佇列*/
static DECLARE_WORK(distance_work,distance_work_func);
/*
中斷處理函式: 用于檢測超聲波測距的回波
*/
static irqreturn_t distance_handler(int irq, void *dev)
{
/*調度作業佇列*/
schedule_work(&distance_work);
return IRQ_HANDLED;
}
static void distance_function(unsigned long data);
/*靜態方式定義內核定時器*/
static DEFINE_TIMER(distance_timer,distance_function,0,0);
/*內核定時器超時處理函式: 觸發超聲波發送方波*/
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);
}
/*修改定時器的超時時間*/
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. 根據GPIO口編號,獲取中斷號*/
distance_irq=gpio_to_irq(EXYNOS4_GPX1(0));
/*3. 注冊中斷*/
err=request_irq(distance_irq,distance_handler,IRQ_TYPE_EDGE_RISING,"distance_device",NULL);
if(err!=0)printk("中斷注冊失敗!\n");
else printk("中斷:超聲波測距驅動安裝成功!\n");
/*4. 修改定時器超時時間*/
mod_timer(&distance_timer,jiffies+msecs_to_jiffies(100));
return 0;
}
static void __exit tiny4412_distance_dev_exit(void)
{
/*5. 注銷中斷*/
free_irq(distance_irq,NULL);
/*6. 停止定時器*/
del_timer(&distance_timer);
/*7. 取消IO映射*/
iounmap(GPB_DAT);
iounmap(GPB_CON);
printk("中斷:超聲波測距驅動卸載成功!\n");
}
module_init(tiny4412_distance_dev_init);
module_exit(tiny4412_distance_dev_exit);
MODULE_LICENSE("GPL");
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/423489.html
標籤:AI
