嵌入式物聯(lián)網(wǎng)畢業(yè)設計選題智能圖像識別項目-stm32mp157 linux開發(fā)板
stm32mp157開發(fā)板FS-MP1A是華清遠見自主研發(fā)的一款高品質、高性價比的Linux+單片機二合一的嵌入式教學級開發(fā)板。開發(fā)板搭載ST的STM32MP157高性能微處理器,集成2個Cortex-A7核和1個Cortex-M4 核,A7核上可以跑Linux操作系統(tǒng),M4核上可以跑FreeRTOS、RT-Thread等實時操作系統(tǒng)。開發(fā)板搭配仿真器、顯示屏、攝像頭、資源擴展板等豐富的擴展模塊,可拓展物聯(lián)網(wǎng)、人工智能等相關技術學習,還可以拓展豐富的項目實戰(zhàn),非常貼合企業(yè)當下開發(fā)需求,是一款嵌入式Linux入門進階必備開發(fā)板!
可學習技術:嵌入式Linux應用/系統(tǒng)/驅動開發(fā)、ARM裸機開發(fā)、Qt界面編程、STM32單片機、FreeRTOS、人工智能機器視覺等。其中ARM Cortex-A7裸機開發(fā)課程是華清遠見獨有特色課程,可關注:https://www.bilibili.com/video/BV1Xe4y1i7vm/,持續(xù)更新中。

14個Linux+Qt綜合項目案例,6個MP1A物聯(lián)網(wǎng)拓展項目
關注公眾號“華清遠見在線實驗室”,回復“mp157項目”,即可領取項目配套文檔及源碼。?
Linux+Qt綜合項目案例:華清遠見stm32mp157開發(fā)板優(yōu)勢特色部分,包括音樂播放器、智慧家庭、智能工業(yè)電表、智能出行助手、智能貓眼、環(huán)境監(jiān)測、智能安防、智能語音識別等10余個項目案例,涉及家居、醫(yī)療、農(nóng)業(yè)多種應用方向,在案例中使用了多種物聯(lián)網(wǎng)和嵌入式技術,包括OT開發(fā)、linux應用開發(fā)、linux驅動開發(fā)、物聯(lián)網(wǎng)云端接入、MQTT協(xié)議、json字符串等知識點。
基于Linux+Qt的智能圖像識別項目
項目簡介:
提到圖像識別,一般都會想到人工智能。雖然現(xiàn)在人工智能還在發(fā)展階段,但是有些技術已經(jīng)成熟,比如圖像識別、語音識別等。本項目將調用百度 AI 開發(fā)平臺 API 進行圖像識別。
開發(fā)平臺:
華清遠見stm32mp157開發(fā)板豪華套餐(開發(fā)板+仿真器+五寸屏+攝像頭+資源擴展板+tf卡+讀卡器)
項目實戰(zhàn):
Qt 開發(fā)環(huán)境搭建
主機開發(fā)環(huán)境說明
1) 本文檔主要介紹 linux 環(huán)境下的 Qt 程序開發(fā);
2) 主機 Qt 版本為 5.14.1;
主機 Qt 環(huán)境搭建及使用
Qt Creator 安裝
將 qt-creator-opensource-linux-x86_64-4.10.1.run(Qt 實驗源碼\工具軟件) 復制到 ubuntu 主機中,可以采用共享文件夾的方式也可以使用 tfp方式將文 件存入家目錄下的 Downloads 目錄。我們需要在終端中賦予安裝程序可執(zhí)行的權限

我們可以使用圖形化的文件管理器來查看

雙擊“qt-creator-opensource-linux-x86_64-4.10.1.run”圖標運行安裝程序。出現(xiàn)如下界面:

等待程序驗證完成后點擊“Next”

這里我們需要登錄或者注冊一個賬號,如果我們之前已經(jīng)注冊過直接登錄就可以。如果沒有注冊過則需要新注冊有一個賬號后登錄。這里筆者已經(jīng)注冊過賬號,所以直接登錄。 登錄成功后出現(xiàn)如下界面,點擊 Next

這里選擇安裝路徑

可以直接默認,Next

這路選擇安裝的組件,直接默認即可

這里我們需要同意用戶協(xié)議

這個界面告訴我們安裝完成后需要占用的空間。點擊”Install”按鈕后開始安裝。

安裝完成后出現(xiàn)如下界面

點擊“Finish”按鈕后將彈出 Qt Creator 主界面

點擊“Cancel”按鈕后即可正常使用
Qt5.14.1 安裝
復制到 qt-opensource-linux-x64-5.14.1.run(Qt 實驗源碼\工具軟件)到 ubuntu 主機中,可以采用共享文件夾的方式也可以使用 tfp 方式將文件存入家目錄下的 Downloads 目錄。進入所在文件夾,先給執(zhí)行權限
輸入命令
chmod +x ./qt-opensource-linux-x64-5.14.1.run
安裝在命令行輸入
./qt-opensource-linux-x64-5.14.1.run
會有可視化引導安裝,一直 next 就行了
在選擇安裝組件的時候要是不知道選擇那些就全選了 大概有 4 個 G 左右
下載 gcc 和 g++
sudo apt-get install gcc g++
下載 cmake
sudo apt-get install cmake
下載鏈接庫
sudo apt-get install libgl1-mesa-dev libglu1-mesa-dev
Qt Creator 配置
1)配置 GCC
運行 QtCreator 后,依次點擊"Tool"->"Options",出現(xiàn)選項對話框,在左側點擊"Kits",右 邊選擇"Compilers"標簽。 檢查有沒有下圖標注的 C++和 C ,般按上面步驟執(zhí)行后都會有

點擊右側"Add"按鈕,彈出下拉列表后,選擇"GCC"的"C"

填寫信息如下,"Name"為"Auto-GCC","Compiler path"點擊旁邊的"Browse.."按鈕選擇編譯器的路徑,例子中的路徑是 “/usr/bin/gcc”

2)配置 G++
點擊右側"Add"按鈕,彈出下拉列表后,選擇"GCC"的"C++",下面的文本框填寫"Name" 為"Auto-G++","Compiler path"點擊旁邊的"Browse.."按鈕選擇編譯器的路徑,例子中的路徑是" /usr/bin/g++"。


填寫完成后,點擊"Apply"。
3)配置 qmake
選擇"Qt Versions"標簽,如果有下面紅框中的文本,可以跳過下面步驟

如果沒有,在右側點擊"Add..."

會彈出 qmake 路徑選擇對話框,這里以"
/home/linux/Qt5.14.1/5.14.1/gcc_64/bin/qmake"為例子。 選擇”qmake”文件后,點擊"Open"按鈕

"Version name"改為" Qt %{Qt:Version} GCC"。然后點擊"Apply"按鈕。
4)配置 Kits
點擊左側"Kits",右側選擇"Kits"標簽。檢查有沒有下圖紅框選中的文本,如果有可以跳過下面步驟

然后沒有,點擊 Add:
在彈出的對話框中"Name"為"Desktop","Device Type"選擇"Desktop"選項, "Sysroot"選擇目標設備的系統(tǒng)目錄,"Compiler"選擇之前配置的名稱"Auto-GCC"和"Auto-G++","Qt version"選擇之前配 置的名稱"Qt 5.14.1GCC",其它默認即可,最后點擊"Apply"和"OK"按鈕。
Qt Creator 新建工程
注意:工程路徑最好不要包含中文、特殊字符、空格等。
我們可以新建一個“qt”文件夾,該文件夾用作我們以后存放源代碼。

打開 Qt Creator,在歡迎頁面點擊 “New”按鈕,來新建一個工程。

在出現(xiàn)的新建項目窗口中,我們選則“Application”->“Qt Widgets Application”,然后點擊右下方“Choose…”按鈕,來創(chuàng)建一個桌面 Qt 應用。

我們在這里設置項目介紹和源碼位置,我們這里創(chuàng)建一個名為“HelloWorld”的示例項目,設置完成之后點擊 next

直接點擊 next

隨后進行細節(jié)設置,主要設置要創(chuàng)建的源碼文件的基本類信息,包括類名等。這里我們可以根據(jù)自己的項目特點進行設置。需要說明的一點就是基類的選擇,這里基類有 QMainWindow、QWidget、QDialog 三種,它們的不同之處如下:
QMainWindow 類提供一個帶有菜單條,工具條和一個狀態(tài)條的主應用程序窗口。主窗口通常提供一個大的中央窗口部件,以及周圍菜單,工具條,和一個狀態(tài)欄。QMainWindow 窗口經(jīng)常被繼承,使得封裝中央部件,菜單,工具條,狀態(tài)欄等都變得很容易,當用戶點擊它的時候,相應的槽就會被調用;
QWidget 類是所有用戶界面對象的基類,窗口部件是用戶界面的一個基本單元,它從窗口系統(tǒng)接收鼠標,鍵盤和其他消息,并在屏幕上繪制自己。一個窗口部件可以被他的父窗口或者是其他窗口擋住一部分;
QDialog 類是對話框窗口的基類,對話框窗口主要用于短期任務和用戶進行短期通訊的頂級窗口,QDialog 可以是模態(tài)對話框或者是非模態(tài)對話框。QDialog 支持擴展并帶有返回值,他們可以帶有默認值;我們在這里選擇 QDialog 類即可,點擊 next 完成類信息設置。

直接點擊 next 按鈕即可。

然后進行工具選擇,該頁面可以選擇我們創(chuàng)建的工程可以使用的工具,選擇想要使用的編譯器模塊,例如下圖 。點擊 next

最后我們設置匯總信息,如果不需要版本控制等功能,直接點擊完成finish 即可。

隨后我們就進入到了主界面,這時候 Qt 已經(jīng)幫我們做好了一些準備工作,包括創(chuàng)建了一些文件,寫好了一些前置代碼等等。
我們可以點擊左邊 protect 欄,來查看我們的編譯選項。

我們可以在左下角選擇編譯 Debug 版或者 Release 版,即調試版或發(fā)行版。

左下角綠色剪頭是編譯并運行,錘子是僅編譯,我們可以直接點擊綠色小箭頭將我們導入的工程編譯并運行起來。

點擊運行按鈕后,我們可以看到 HelloWorld 窗口運行起來了。

導入工程
我們可以將已存在的 Qt 程序項目直接打開,這里以上一章節(jié)的HelloWorld 程序為例。首先我們確定源碼存在的位置,如 HelloWorld 程序源碼在 /home/linux/qt/helloworld 路徑下
點擊歡迎頁面的“Open” 按鈕可以打開已有的工程

找到我們剛才解壓好的源碼,選擇“helloworld.pro”文件并點擊打開

接下來我們就可以進入到代碼編輯界面了。

左上角是項目欄,點擊項目名稱左邊的小箭頭可以展開項目目錄

我們可以點擊左邊項目欄,來查看我們的編譯選項。需注意的是構建設置中的路徑應與工程路徑處于同級目錄下。

我們可以在左下角選擇編譯 Debug 版或者 Release 版,即調試版或發(fā)行版。

左下角綠色剪頭是編譯并運行,錘子是僅編譯,我們可以直接點擊綠色小箭頭將我們導入的工程編譯并運行起來

點擊運行按鈕后,我們可以看到 HelloWorld 窗口運行起來了。

Qt Creator 文件說明
通過上面兩個章節(jié),我們學習到了 Qt 程序的新建與導入的方法,也知道了Qt 會幫我們做一些基礎工作,比如幫我們建立了一些文件,那么這些文件都是干什么用的呢?我們以 HelloWorld 程序來說明一下。

以“.pro”為后綴名的文件,為 Qt 的項目管理文件,存儲項目設置的文件;

“Qt += core gui”表示項目中加入 core gui 模塊。core gui 是 Qt 用于GUI 設計的類庫模塊,如果創(chuàng)建的是控制臺(console)應用程序,就不需要添加 core gui。
Qt 類庫以模塊的形式組織各種功能的類,根據(jù)項目涉及的功能需求,在項目中添加適當?shù)念悗炷K支持。例如,如果項目中使用到了涉及數(shù)據(jù)庫操作的類就需要用到 sql(數(shù)據(jù)庫)模塊,在 pro 文件中需要在后面加上 sql:
1 Qt += core gui sql
“greaterThan(QT_MAJOR_VERSION, 4): QT += widgets”,這是個條件執(zhí)行語句,表示當 Qt 主版本大于 4 時,才加入 widgets 模塊。
“TARGET = HelloWorld”表示生成的目標可執(zhí)行文件的名稱,即編譯后生成的可執(zhí)行文件是 HelloWorld.exe。
“TEMPLATE = app”表示項目使用的模板是 app,是一般的應用程序。
后面的 SOURCES、HEADERS、FORMS 記錄了項目中包含的源程序文件、頭文件和窗體文件(.ui 文件)的名稱。這些文件列表是 Qt Creator 自動添加到項目管理文件里面的,用戶不需要手動修改。當添加一個文件到項目,或從項目里刪除一個文件時,項目管理文件里的條目會自動修改。
文件夾“Header”中,存放的是所設計的窗體類的頭文件;
文件夾“Sources”中,存放著源碼文件。main.cpp 是實現(xiàn) main()函數(shù)的程序文件,HelloWorld.cpp 是 widget.h 里定義類的實現(xiàn)文件。C++中,任何窗體或界面組件都是用類封裝的,一個類一般有一個頭文件(.h 文件)和一個源程序文件(.cpp 文件);
文件夾“Forms”中,存放著界面設計文件,“.ui”文件是一個 XML 格式存儲的窗體上的元件及其布局的文件,雙擊項目文件目錄樹中的文件 ui,會打開一個集成在 Qt Creator 中的 Qt Designer 對窗體進行可視化設計;

UI 設計器有以下一些功能區(qū)域:
組件面板:窗口左側是界面設計組件面板,分為多個組,如 Layouts、Buttons、Display Widgets 等,界面設計的常見組件都可以在組件面板里找到。
中間主要區(qū)域是待設計的窗體。如果要將某個組件放置到窗體上時,從組件面板上拖放一個組件到窗體上即可。
Signals 和 Slots 編輯器與 Action 編輯器是位于待設計窗體下方的兩個編輯器。Signals 和 Slots 編輯器用于可視化地進行信號與槽的關聯(lián),Action 編輯器用于可視化設計 Action。
布局和界面設計工具欄:窗口上方的一個工具欄,工具欄上的按鈕主要實現(xiàn)布局和界面設計。
對象瀏覽器(Object Inspector):窗口右上方是 Object Inspector,用樹狀視圖顯示窗體上各組件之間的布局包含關系,視圖有兩列,顯示每個組件的對象名稱(ObjectName)和類名稱。
屬性編輯器(Property Editor):窗口右下方是屬性編輯器,是界面設計時最常用到的編輯器。屬性編輯器顯示某個選中的組件或窗體的各種屬性及其取值,可以在屬性編輯器里修改這些屬性的值。屬性編輯器的內容分為兩列,左側為屬性的名稱,右側為屬性的值。屬性又分為多個組,實際上表示了類的繼承關系,位于下方的類屬性組繼承自位于上方的類屬性組;
如果我們需要新建資源文件、源碼文件等,可以在項目文件夾出點擊鼠標右鍵,選擇 Add New;如果我們有新的文件需要添加,可以在項目文件夾出點擊鼠標右鍵,選擇 Add Existing Files。

幫助文檔
Qt 的幫助文檔是伴隨我們學習 Qt 開發(fā)的好伙伴。在 Qt 開發(fā)過程中,我們會面臨圖形接口使用的問題,它不像 C 語言那樣就那么幾個函數(shù)接口,圖形接口的接口數(shù)量可以用海量來形容,常用的我們可能能記住,其它的就沒有必要去記了,用到什么就去幫助文檔查看用法是比較方便的。我們可以按 F1 按鍵,或通過上方導航欄的“help->contects”來進入幫助文檔。

上方的前進后退按鈕方便我們查看文檔,如返回到上一步,返回到下一步。

我們可以通過幫助文檔來查看以下幾個部分:類使用的相關介紹;
查看相關類的使用介紹,我們可以先進入到幫助文檔,然后在左上角選擇“Search”。筆者這里以 QWidget 類為例,輸入我們想要查找的類的名字,然后雙擊查找結果來查看說明。


也可以先將鼠標移動到想要查詢的類的位置,如圖所示,將鼠標移動至“QWidget”處,然后按“F1”鍵,即可跳轉到相應的幫助文檔。


我們可以通過再按一次“F1”鍵來全窗口查看幫助文檔,按“Esc”鍵可以退出。

部分常用的成員元素包括以下幾項:
公有成員函數(shù):操作部件屬性的相關函數(shù);
公有槽函數(shù):Qt 類中已經(jīng)定義好的槽函數(shù),直接可與信號相連接;
信號:軟中斷,如按下按鈕觸發(fā) pressed() 信號等;
保護成員函數(shù):通常事件所對應的虛函數(shù)放在此處;
事件:常用事件,如操作鼠標觸發(fā)的鼠標事件;
滾動鼠標滾輪,向下即可看到“Qwdget Class”類的相關說明了。
部分常用的成員元素包括以下幾項:
公有成員函數(shù):操作部件屬性的相關函數(shù);
公有槽函數(shù):Qt 類中已經(jīng)定義好的槽函數(shù),直接可與信號相連接;
信號:軟中斷,如按下按鈕觸發(fā) pressed() 信號等;
保護成員函數(shù):通常事件所對應的虛函數(shù)放在此處;
事件:常用事件,如操作鼠標觸發(fā)的鼠標事件;
滾動鼠標滾輪,向下即可看到“Qwdget Class”類的相關說明了。

1) 查看所用的部件的相應成員函數(shù)。
我們可以查找到該類所用部件的相應成員函數(shù)的使用方法、功能、參數(shù)、返回值等等,我們以“按鈕”控件,即“QPushButton Class”類為例,我們通過索引搜索的方式,來找到這個類

我們可以通過點擊“Public Functions” 來查看“QPushButton”這個類中的成員函數(shù)。

這里以“QPushButton(const QString &text, QWidget *parent =Q_NULLPTR)”為例,我們點擊函數(shù)名字可以進入到函數(shù)詳情中。我們可以看到相應的描述為:以“text”為顯示內容,以“parent”為父對象,構造一個push 按鈕?!皌ext”“parent”為函數(shù)參數(shù),由于是構造函數(shù),所以此函數(shù)沒有返回值。

還有一些函數(shù)是繼承自其它類的,例如“Public Functions”中有 21 個繼承自“QAbstractButton”類的函數(shù),我們點擊“QAbstractButton”即可查看。擊“QAbstractButton”即可查看

同樣我們可以點擊相應的函數(shù)進入查看詳情。如查看“voidsetText(const QString &text)”。

2) 查看所用的部件的信號。
我們這里還是以“PushButton”為例,我們點擊“Public Slots”。

可以看到“PushButton”本身有一個“void showMenu()”的信號,并且有很多繼承自其他類的信號。

一般來說我們用的“PushButton”的信號,最多的是用到其繼承自基類“QAbstractButton”中的幾個信號,分別是點擊(按下后抬起)、按壓(單按下)、釋放(單抬起)等

我們可以點擊相應信號查看詳情

3) 查看所用的部件的事件(所對應的虛函數(shù)如何編寫)。部件常用事件主要在 “QWidget”中聲明,選擇“Events”即可查看相關說明。
每個事件都對應著事件函數(shù)。

點擊事件函數(shù)可查看詳情

實驗步驟
UI 界面設計
由于我們配置的七寸屏幕是 1024*768 分辨率的,所以我們的 MainWindow主界面的尺寸設置為 1024*768。共使用如下幾個控件,使用 QTextEdit 控件textEdit 來顯示語音識別后返回的最佳匹配語音。使用 QPushButton 控件pushButton_video 點擊錄音和釋放識別,使用 pushButton_clear 來清空 QtextEdit的內容,使用 textEdit_2 來顯示傳感器的反饋。
邏輯實現(xiàn)
獲取圖像
在 pro 文件添加
QT += network
QT += multimedia
使用 V4L2 進行圖像采集,新建v4l2api.h 和 v4l2api.cpp。


采集/dev/video0 攝像頭設備的圖像,但是采集到的是 yuyv 格式的圖像,需要進行轉換成 rgb 格式才能顯示在 lcd 屏幕上面。
主要功能代碼如下:
void V4l2Api::run()
{
?char buffer[WIDTH*HEIGHT*3];
?char rgbbuffer[WIDTH*HEIGHT*3];
?int len;
?while(1)
?{
?grapImage(buffer, &len);
?yuyv_to_rgb888((unsigned char *)buffer, (unsigned char *)rgbbuffer);
?//把 RGB 數(shù)據(jù)轉為 QImage
?QImage image((uchar*)rgbbuffer, WIDTH, HEIGHT,
QImage::Format_RGB888);
?emit sendImage(image);
?msleep(5);
?}
}
Yuyv 轉 RGB 函數(shù)實現(xiàn)
bool V4l2Api::yuyv_to_rgb888(unsigned char *yuyvdata, unsigned char *rgbdata,
int picw, int pich)
{
?int i, j;
?unsigned char y1,y2,u,v;
?int r1,g1,b1,r2,g2,b2;
?//確保所轉的數(shù)據(jù)或要保存的地址有效
?if(yuyvdata == NULL || rgbdata == NULL)
{
?return false;
?}
?int tmpw = picw/2;
?for(i=0; i<pich; i++)
?{
?for(j=0; j<tmpw; j++)// 640/2 == 320
?{
?//yuv422
?//R = 1.164*(Y-16) + 1.159*(V-128);
?//G = 1.164*(Y-16) - 0.380*(U-128)+ 0.813*(V-128);
?//B = 1.164*(Y-16) + 2.018*(U-128));
?//下面的四個像素為:[Y0 U0 V0] [Y1 U1 V1] -------------[Y2 U2
V2] [Y3 U3 V3]
?//存放的碼流為: Y0 U0 Y1 V1------------------------Y2 U2 Y3
V3
?//映射出像素點為: [Y0 U0 V1] [Y1 U0 V1]--------------[Y2 U2
V3] [Y3 U2 V3]
?//獲取每個像素 yuyv 數(shù)據(jù) YuYv
?y1 = *(yuyvdata + (i*tmpw+j)*4); //yuv 像素的
Y
?u = *(yuyvdata + (i*tmpw+j)*4+1); //yuv 像素
的 U
?y2 = *(yuyvdata + (i*tmpw+j)*4+2);
?v = *(yuyvdata + (i*tmpw+j)*4+3);
?//把 yuyv 數(shù)據(jù)轉換為 rgb 數(shù)據(jù)
r1 = 1.164*(y1-16) + 2.018*(u-128);
?g1= 1.164*(y1-16) - 0.380*(v-128)- 0.394*(v-128);
?b1 = 1.164*(y1-16) + 1.159*(v-128);
?r2 = 1.164*(y2-16) + 2.018*(u-128);
?g2= 1.164*(y2-16) - 0.380*(v-128)- 0.394*(v-128);
?b2 = 1.164*(y2-16) + 1.159*(v-128);
?if(r1 > 255) r1=255;
?else if(r1 < 0) r1 = 0;
?if(g1 > 255) g1=255;
?else if(g1 < 0) g1 = 0;
?if(b1 > 255) b1=255;
?else if(b1 < 0) b1 = 0;
?if(r2 > 255) r2=255;
?else if(r2 < 0) r2 = 0;
?if(g2 > 255) g2=255;
?else if(g2 < 0) g2 = 0;
?if(b2 > 255) b2=255;
?else if(b2 < 0) b2 = 0;
?rgbdata[((i+1)*tmpw+j)*6] = (unsigned char)b1;
?rgbdata[((i+1)*tmpw+j)*6 + 1] = (unsigned char)g1;
?rgbdata[((i+1)*tmpw+j)*6 + 2] = (unsigned char)r1;
?rgbdata[((i+1)*tmpw+j)*6 + 3] = (unsigned char)b2;
?rgbdata[((i+1)*tmpw+j)*6 + 4] = (unsigned char)g2;
rgbdata[((i+1)*tmpw+j)*6 + 5] = (unsigned char)r2;
?}
?}
?memcpy(yuyvdata,rgbdata,HEIGHT*WIDTH*3);
?return true;
}
獲取、關閉獲取圖像、拍照按鈕槽函數(shù)
右鍵采集圖像按鈕,點擊轉到槽。其他兩個按鈕同樣。


函數(shù)實現(xiàn)如下:

申請百度 AI 開發(fā)平臺圖像識別應用
圖像識別是利用百度的 API 在線識別。所以需要申請項目 ID。
首先登陸 http://ai.baidu.com/tech/imagerecognition/general,進入到通用圖像分析的界面。選擇立即使用

登陸自己的百度賬號,可用手機號申請。
點擊創(chuàng)建應用:

依次輸入應用名稱,選擇類型,接口默認選擇圖像識別,添加應用描述,點擊立即創(chuàng)建。

至此,應用創(chuàng)建完畢,現(xiàn)在就可以使用該應用了。

點擊返回應用列表,我們記住其中的 API Key 和 Secret Key,下面會用到。

請求類實現(xiàn)
我們采集的圖像需要通過 HTTPS 協(xié)議上傳到百度 AI 開發(fā)平臺進行識別,之后 AI 平臺會返回給我們識別的結果。
http 類只需要封裝一個方法
static bool post_sync(QString url,QMap<QString,QString>header,QByteArray requestData,QByteArray &replyData);
使用這個方法去 URL 發(fā)送請求會收到 URL 的返回值。
http.h
#ifndef HTTP_H
#define HTTP_H
#include <QObject>
#include <QMap>
#include <QNetworkAccessManager>
#include <QNetworkRequest>
#include <QNetworkReply>
#include <QEventLoop>
#include <QDebug>
class Http : public QObject
{
?Q_OBJECT
public:
?explicit Http(QObject *parent = nullptr);
?static bool post_sync(QString
url,QMap<QString,QString>header,QByteArray requestData,QByteArray
&replyData);
signals:
};
#endif // HTTP_H
http.cpp
這個方法的第一個參數(shù)是 post 方法發(fā)送請求的 URL,第二個參數(shù)是請求的方法頭,第三個參數(shù)是請求的數(shù)據(jù),第四個參數(shù)是返回的數(shù)據(jù)。這里要說的是必須要設置 openssl 簽名配置,否則在 ARM 上會報錯
bool Http::post_sync(QString url,QMap<QString,QString>header,QByteArray
requestData,QByteArray &replyData)
{
// 發(fā)送請求的對象
?QNetworkAccessManager manager;
// 請求 對象
?QNetworkRequest request;
?request.setUrl(url);
?QMapIterator<QString,QString> it(header);
?while (it.hasNext()) {
?it.next();
?request.setRawHeader(it.key().toLatin1() ,it.value().toLatin1());
?}
//設置 openssl 簽名配置,否則在 ARM 上會報錯
?QSslConfiguration conf = request.sslConfiguration();
?conf.setPeerVerifyMode(QSslSocket::VerifyNone);
#if (QT_VERSION > QT_VERSION_CHECK(5,0,0))
?conf.setProtocol(QSsl::TlsV1_0);
#else
?conf.setProtocol(QSsl::TlsV1);
#endif
?request.setSslConfiguration(conf);
?QNetworkReply *reply = manager.post(request,requestData);
QEventLoop l;
?//一旦服務器返回,reply 會發(fā)出信號
?connect(reply,&QNetworkReply::finished,&l,&QEventLoop::quit);
?l.exec();
?if(reply != nullptr && reply->error() == QNetworkReply::NoError)
?{
?replyData = reply->readAll();
?return true;
?}
?else
?{
?qDebug()<<"request error!";
?return false;
?}
}
采集到的圖像處理
查看百度 ai 開發(fā)平臺接口文檔,我們看到 http 請求的 image 需要進行處理,圖片需要 base64 編碼、去掉編碼頭后再進行 urlencode。

新建 ImageProcess 類實現(xiàn)以下函數(shù),返回 QbyteArray 類型的圖像。
QByteArray IamgeProcess::imageBaseTo64ToUrlEncode(QString imagePth)
{
?QImage image(imagePth);
?QByteArray byte;
?//用 QByteArray 構造 QBuffer
?QBuffer buf(&byte);
?buf.open(QIODevice::WriteOnly);
?image.save(&buf,"JPG");
?//對圖片做 base64 編碼(不包含編碼頭)
?QByteArray byteBase64 = byte.toBase64();
?QTextCodec *codec = QTextCodec::codecForName("UTF-8");
?QByteArray imgData =
codec->fromUnicode(byteBase64).toPercentEncoding();
?return imgData;
}
?MainWindow 類發(fā)送請求
需要向百度 AI 平臺發(fā)送兩個請求,第一個請求是獲取 access_token;第二個請求是向 URL 發(fā)送圖片資源。
1.獲取 access_token

我們復制示例中的 url 地址如下。
https://aip.baidubce.com/oauth/2.0/token?grant_type=client_credentials&
client_id=Va5yQRHlA4Fq5eR3LT0vuXV4&client_secret=0rDSjzQ20XUj5itV6WRtzn
PQSzr5pVw2&
把其中的 client_id 和 client_secret 后面的參數(shù)刪掉,通過二維碼掃描的方
式加入 URL 如下:
https://aip.baidubce.com/oauth/2.0/token?grant_type=client_credenti
als&client_id=%1&client_secret=%2&
我們通過二維碼生成器把我們的 API Key 和 Secret Key 寫成 josn 的形式生成二維碼,如以下形式:
{
“client_id”:“xxxxxx”,
“client_secret”:“xxxxxx”
}
我們在下面開始實現(xiàn)通過識別二維碼填充 client_id 和 client_secret 到上述的URL 中。
右鍵轉到槽,選擇 clicked()。


在這里識別二維碼需要使用到 QZXing 庫進行識別。我們提 QZXing 庫的源代碼在實驗源碼下的 qzxing.tar.xz。
解壓后,將解壓后的文件放到 QT 源碼路徑下


在 pro 文件下添加 include(qzxing/src/QZXing.pri)保存后,在 mainwindow.h 加入
#include< QZXing >頭文件,這樣就可以使用 QZXing 庫了。下面開始編寫識別二維碼填充 URL。
在 mainwindow.cpp 添加下面 QString 定義。

void MainWindow::on_pushButton_ewm_clicked()
{
?if(picTorF == false)
?{
?QMessageBox::warning(this, "警告", "請先拍照保存圖片");
?return ;
?}
?QZXing zxing;
?QString imagePth ="./pic.jpg";
?QImage image(imagePth);
?QByteArray byte = zxing.decodeImage(image).toUtf8();// 該 方 法 返 回
QString 串,標識圖片二維碼的內容
?QJsonObject obj = QJsonDocument::fromJson(byte).object();
?client_id = obj.value("client_id").toString();
?secret_id = obj.value("secret_id").toString();
?qDebug()<< "client_id:"<<client_id;
?qDebug()<< "secret_id:"<<secret_id;
?if(client_id =="")
?{
?QMessageBox::warning(this, "警告", "請重新填充秘鑰");
?on_openBt_clicked();
?return ;
?}
?else
?{
?QMessageBox::information(this, "提示", "填充秘鑰成功");
?ui->pushButton_ewm->setText("填充完成");
ui->pushButton_ewm->setEnabled(false);
?Keypadding = true;
?picTorF = false;
?on_comboBox_activated(0);
?on_openBt_clicked();
?}
}
2.???? 上傳圖片資源
我們查看百度 ai 平臺文檔,可以看到每種物體識別都有不同的 URL




所以我們可以通過改變下拉框來改變圖片請求的 URL 從而實現(xiàn)不同物體的識別。


void MainWindow::on_comboBox_activated(int index)
{
?Q_UNUSED(index)
?QByteArray img = IamgeProcess::imageBaseTo64ToUrlEncode("pic.jpg");
//image=xxxxxxx
?QByteArray imgData = "image=" + img; //body
?//獲取 access_token
?QByteArray replyData; //保存回復信息
?QString url = QString(baiduTokenUrl).arg(client_id).arg(secret_id);
?QMap<QString, QString> header; //封裝頭部信息
?header.insert(QString("Content-Type"), QString("application/x-www-formurlencoded"));
bool result = Http::post_sync(url, header, imgData, replyData);
?if (result)
?{
?QJsonObject obj = QJsonDocument::fromJson(replyData).object();
?accessToken = obj.value("access_token").toString();
?}
?switch (ui->comboBox->currentIndex())
?{
?case 0:
?imgUrl = baiduImageUrl.arg("v1").arg("animal").arg(accessToken);
?break;
?case 1:
?imgUrl = baiduImageUrl.arg("v2").arg("logo").arg(accessToken);
?break;
?case 2:
?imgUrl =
baiduImageUrl.arg("v1").arg("classify/ingredient").arg(accessToken);
?break;
?case 3:
?imgUrl = baiduImageUrl.arg("v1").arg("plant").arg(accessToken);
?break;
?}
}
?{
?for(int i=0;i<3;i++)
?{
?QJsonValue first = val.toArray().at(i);
if (first.isObject())
?{
?QString name = first.toObject().value("name").toString();
?QString score = first.toObject().value("score").toString();
ui->textEdit->append(QString(QString::number(i+1)).append(". 名 稱 :
").append(name).append("\n 置信度: ").append(score));
?}
?}
// 顯示最終結果
?ui->label_3->setText("經(jīng)圖像分析最可能為");
ui->label_4->setText(val.toArray().at(0).toObject().value("name").toString());
?}
?else{
?ui->textEdit->append("識別不到,請重新拍照識別");
?}
?}
?else{
?ui->textEdit->append("識別不到,請重新拍照識別");
?}
}

右鍵圖像識別,轉到槽
void MainWindow::on_recognitionBt_clicked()
{
?ui->textEdit->clear();
?ui->label_3->clear();
?ui->label_4->clear();
?if(Keypadding ==false)
?{
?QMessageBox::warning(this, "警告", "請先填充秘鑰");
?return ;
?}
?if(picTorF == false)
?{
?QMessageBox::warning(this, "警告", "請先拍照保存圖片");
?return ;
?}
?QByteArray img = IamgeProcess::imageBaseTo64ToUrlEncode("pic.jpg");
//image=xxxxxxx
?QByteArray imgData = "image=" + img; //body
?//獲取 access_token
?QByteArray replyData; //保存回復信息
?QString url = QString(baiduTokenUrl).arg(client_id).arg(secret_id);
?QMap<QString, QString> header; //封裝頭部信息
?header.insert(QString("Content-Type"), QString("application/x-www-formurlencoded"));
?bool result = Http::post_sync(imgUrl, header, imgData, replyData);
?if (result)
?{
?QJsonObject obj = QJsonDocument::fromJson(replyData).object();
?QJsonValue val = obj.value("result");
?qDebug()<< obj;
?if (val.isArray())
實驗源碼
源碼路徑【11_智能圖像識別\實驗源碼\05-AiCamera】
注意事項
1.在開發(fā)板運行時,需要導入中文字庫,否則會因為識別不了中文。
將【11_智能圖像識別\工具軟件\wqy-zenhei-0.9.47-nightlybuild.tar.gz 或 wqy-zenhei-0.8.38-1.tar.gz】復制到 ubuntu 下。并使用 scp 命令將文件拷貝到開發(fā)板的 usr/share/fonts 目錄下,使用 tar 命令解壓后即可。?
linux@ubuntu:~$ scp wqy-zenhei-0.8.38-1.tar.gz
root@192.168.10.128:/usr/share/fonts/

2.如果使用 mipi 五寸屏運行此項目,需要進行屏幕旋轉以適應屏幕,具體步驟如下:
在/etc/profile.d/qt-eglfs.sh 添加環(huán)境變量如下:


下面變量的 event0 設備需要填實際的觸摸屏設備

這里即填 event0
export QT_QPA_EGLFS_ROTATION=90
export QT_QPA_EGLFS_NO_LIBINPUT=1
export
QT_QPA_EVDEV_TOUCHSCREEN_PARAMETERS=/dev/input/event0:rotate=90