如何基於Flutter和Paddle Lite實現實時目標檢測

 

很早之前接觸到了飛槳(PaddlePaddle)以及PaddleDetection工具,被他們的簡單易用吸引,同時,這些工具極大降低了訓練模型的門檻並減少了所需時間,非常適合新手入門。在很多實際應用場景也有不俗的表現。

在端側部署方面,Paddle Lite是飛槳產品棧中用於端側高性能輕量化AI應用部署的推理引擎,給了移動端等場景更多可能。這款引擎允許我們在很多硬件平臺上實現輕量化的高效預測,進行一次預測耗時較短,也不需要太多的計算資源。

那麼如果我們想開發一款既能在本地進行預測又能在Android和iOS上面有一致體驗的App的話,Flutter無疑是一個好選擇。其作爲開源移動UI框架已然成爲跨平臺移動開發一大趨勢,在開發時可以保留狀態進行熱重載,內置許多令人眼前一亮的組件和漂亮的動畫,同時還能保證性能達到和原生應用一樣。也正因爲這樣,不少公司開始把自己的應用向Flutter遷移,有許多我們耳熟能詳的App其實已經是基於Flutter開發。假如你已經對安卓原生開發十分熟悉的話,不妨去試試。

這次我們就基於Flutter來開發一個實時目標檢測程序,這也得益於Flutter支持訪問iOS和Android上的原生系統功能和系統SDK。

我們項目的GitHub地址:

https://github.com/KernelErr/realtime-object-detector

其中內置了水果識別模型,下載下來就能直接編譯體驗。約定:

  • Flutter端:Flutter項目主目錄。

  • Android端:項目的Android子目錄,原生安卓。

 

開發環境

我們在開發的時候環境如下:

  • Flutter version 1.12.13+hotfix.8

  • Dart version 2.7.0

  • Android Studio (version 3.6)

  • Android toolchain - develop for Android devices (Android SDK version 29.0.3)

Flutter在更新的同時加入了越來越多新的特性,網上一些基於老版本的實現方法已經不太實用,我們需要進行一些修改。

 

準備模型

Paddle Lite需要通過opt工具生成其支持的輕量化模型,如果你手上已經有PaddleDetection訓練出來的模型,那麼你需要先在PaddleDetection導出模型,然後通過opt工具進行轉換。

如果你有其他框架訓練出來的模型,如caffe、tensorflow、onnx等,可以利用X2Paddle來轉換。

假設我們已經得到了兩個文件:

  • model.nb - 基於Yolov3 Tiny訓練且已經通過opt優化好的模型

  • label - 模型預測一一對應的標籤

 

如何在Flutter中支持Paddle Lite?

我們只需要通過Android Studio創建一個新的Flutter項目,這裏我們假設名字是realtime_od。

準備Paddle Lite的預測庫和模型文件

由於我們使用的是安卓原生代碼,所以我們需要在Android端進行開發,而不是Flutter端。我們在Paddle Lite提供的預編譯預測庫裏面下載需要的預編譯庫,放到Android端的相應文件夾內,和原生安卓的目錄類似。之後我們繼續在android文件夾內放置模型文件,在realtime_od/android/app/src/main/下面新建assets文件夾,並分別把模型和標籤放到models和labels子文件夾內。這時候你的目錄結果應該是這樣:

我們使用口罩模型作爲樣例,模型位置是:models/mask/model.nb,標籤位置是:labels/mask_label_list。因此你需要在MainActivity裏面賦值:

 

禁用壓縮

在生成APK的時候,我們的模型會被壓縮,所以我們需要修改build.gradle配置文件來禁用assets文件夾的壓縮。

 

提供原生安卓支持

如果爲了Flutter的支持,給Paddle Lite專門寫一套Dart調用代碼是工作巨大的,所以我們不妨直接基於官方的Demo進行修改。在Android端,我們直接使用了官方Demo中的代碼,並在MainActivity內註冊了Channel。

由於Flutter中加入了進程安全機制,我們使用了一個MethodResultWrapper保證在主進程裏面返回result。新版Flutter中你需要使用configureFlutterEngine而不是onCreate來註冊組件。

 

使用實時影像

讓我們來給Flutter提供來自攝像頭的實時影像!添加一下Flutter的camera插件,Dart 已經有很多現成的包給我們使用:

同時需要確保項目的最低Android SDK版本在21以上。在官方提供的Demo中,圖片輸入使用的是Bitmap圖片,但是我們從插件得到的格式是android.graphics.ImageFormat.YUV_420_888,在Predictor類的最下面我們進行了相應的轉換,轉換代碼的使用已經聯繫原作者獲得授權。我們在其中使用了RenderScript進行高效計算,避免延遲過高。

顯示實時圖像並標註

大量的工作都花在了Android端上面,下面讓我們來Flutter端做些工作。

在main.dart和object_detector.dart裏面你可以發現我們調用Android端提供的方法,即loadModel以及detectObject。同時在DrawObjects類裏面提供了標註目標的功能,代碼相對比較簡單,利用得到的預測結果進行畫圖。

 

Let’s run it!

這裏使用的是羣友提供的口罩模型,label文件裏面只有兩行,分別是戴口罩和未帶口罩。我們在Android 9設備上面用PaddlePaddle官方示例圖片測試一下。

從日誌上面可以看出Paddle Lite預測的時間是接近700 ms。

 

更改模型和優化方案

如何使用其他模型

我們是參考羣友的解決方案(參考鏈接裏面給出)適配的YOLO v3,主要的修改在Predictor內的模型輸入以及MainActivity的初始化。因爲官方使用的是其他模型,輸入的Shape和我們不一樣,我們的是320。

如果你需要使用其他模型,請同步修改輸入處的:

以及輸出處的:

標註函數處也需要做相應修改,修改main.dart:

 

怎麼更快

實際上我們的模型還不夠快,選擇合適的模型,可以把預測時間縮短到更短。具體還是看自己的需要,Paddle Lite支持許多主流的模型,大家可以進行選用。

 

Trouble Shooting

記錄的問題包括Flutter開發過程中遇到的和Paddle Lite使用中遇到的:

 

1. Methods marked with @UiThread must be executed on the main thread.

這是因爲Flutter引入了進程安全,不能直接在子進程裏面返回result,需要在主進程裏面返回,網上現在有很多解決辦法,我們的也是來自GitHub。

 

2. 錯誤: 不兼容的類型: MainActivity無法轉換爲FlutterEngine

很可能你看的教程是舊版本,請直接參考官方文檔寫原生安卓。我們在原生安卓開發的時候指定了v2。

 

3. Paddle Lite出現庫錯誤

一開始以爲是官方的問題,但是自己手動編譯一次庫就能解決。我已經內置了arm64的無問題的庫。

 

4. 其他問題

官方文檔 -> GitHub -> 搜索引擎 -> Paddle Lite官方QQ羣(696965088),一般都能解決。:)

 

參考鏈接

Paddle Lite Github地址:

https://github.com/PaddlePaddle/Paddle-Lite

Paddle Lite中文文檔:

https://paddle-lite.readthedocs.io/zh/latest/index.html

Paddle Lite 安卓端部署:

https://www.ralphlu.top/article/2020/3/4/7.html

Real-Time Object Detection with Flutter, TensorFlow Lite and Yolo -Part 1:

https://blog.francium.tech/real-time-object-detection-on-mobile-with-flutter-tensorflow-lite-and-yolo-android-part-a0042c9b62c6

Writing custom platform-specific code:

https://flutter.dev/docs/development/platform-integration/platform-channels

PaddleDetection地址:

https://github.com/PaddlePaddle/PaddleDetection

飛槳官網地址:

https://www.paddlepaddle.org.cn

飛槳開源框架項目地址:

GitHub: https://github.com/PaddlePaddle/Paddle

Gitee: https://gitee.com/paddlepaddle/Paddle

END

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章