用樹莓派4b構建深度學習應用(六)TensorFlow Lite篇

2021-02-20 深度覺醒

上回我們建立了 tensorflow 的開發環境,跑測試模型比較方便,但對於樹莓派來說,還是太龐大了。僅有 0.3fps 無法滿足實時的生產環境需求,這篇我們部署一下專門為移動端和嵌入式設備而生的 TensorFlow Lite,並跑幾個模型,測試一下純樹莓派上的極限幀率。

TensorFlow Lite 是一組工具,可幫助開發者在行動裝置、嵌入式設備和 IoT 設備上運行 TensorFlow 模型。它支持設備端機器學習推斷,延遲較低,並且二進位文件很小。

TensorFlow Lite 包括兩個主要組件:

轉換器一般在主電腦上完成,主要是為了靜態化計算圖,轉換權重類型後,生成 .tflite 文件。而解釋器主要在嵌入式設備上運行,我們這裡先在樹莓派上安裝一下 tensorflow lite。

 1   建立虛擬環境

python3 -m venv --system-site-packages ~/my_envs/tf_litesource ~/my_envs/tf_lite/bin/activate

 2   安裝 2.1.0 版本

wget https://dl.google.com/coral/python/tflite_runtime-2.1.0.post1-cp37-cp37m-linux_armv7l.whlpip install tflite_runtime-2.1.0.post1-cp37-cp37m-linux_armv7l.whl

 3   啟用 opencv

cd ~/my_envs/tf_lite/lib/python3.7/site-packagesln -s /usr/local/lib/python3.7/site-packages/cv2 cv2

 4   安裝完成

import tflite_runtime.interpreter as tflitetflite.Interpreter

 1   測試攝像頭

先保證攝像頭排線已插入樹莓派的 CSI 接口,並在 raspi-config 裡 Interfacing options -> camera 選項裡啟用了攝像頭。

# 拍攝照片raspistill -o demo.jpg# 錄製視頻raspivid -o vid.h264

看一下目錄裡是否有拍攝的 demo.jpg 照片和 vid.h264 視頻文件,保證硬體沒有問題。

 2   使用 picamera 控制攝像頭

拍攝一張照片

import picamerafrom time import sleep
camera = picamera.PiCamera()try: camera.resolution = (1024, 768) camera.brightness = 60 camera.start_preview() camera.annotate_text = 'Raspberry Pi' sleep(3) camera.capture('image1.jpeg')finally: camera.stop_preview() camera.close()

一定要記得用完攝像頭後用 camera.close() 關閉,或是用 With 子句自動釋放資源。否則會收到 picamera.exc.PiCameraMMALError: Failed to enable connection: Out of resources 的錯誤信息,只能 Kill python 進程強制釋放了。

錄製一段視頻

with picamera.PiCamera() as camera:    camera.resolution = (640, 480)    camera.start_preview()    camera.start_recording('video.h264')    camera.wait_recording(10)    camera.stop_recording()

 3   使用 opencv 控制攝像頭

import cv2
cap = cv2.VideoCapture(0)cap.set(cv2.cv.CV_CAP_PROP_FRAME_WIDTH, 640)cap.set(cv2.cv.CV_CAP_PROP_FRAME_HEIGHT, 480)
while True: ret, frame = cap.read()        cv2.imshow("capture", frame)     if(cv2.waitKey(1) == ord('q')): cv2.destroyAllWindows()        break

如果在OpenCV中調用CSI攝像頭會出現無數據的現象,這是因為樹莓派中的camera module是放在/boot/目錄中以固件形式加載的,不是一個標準的V4L2的攝像頭驅動,所以加載起來之後會找不到/dev/video0的設備節點。我們在/etc/modules裡面添加一行bcm2835-v4l2 就能解決問題。

添加:bcm2835-v4l2,保存關閉即可。

 4   查詢其他 usb 視頻設備

Jupyter Notebook是一個開源的Web應用程式,允許用戶創建和共享包含代碼、方程式、可視化和文本的文檔。廣泛的用於各種雲平臺上,為了後續代碼的可移植性,我們這裡先安裝一下。

 1   安裝 jupyter

 2   創建配置文件

創建Jupyter notebook的配置文件jupyter_notebook_config.py,在終端中輸入:

jupyter notebook --generate-configsudo nano ~/.jupyter/jupyter_notebook_config.py

編輯配置文件 jupyter_notebook_config.py

c.NotebookApp.ip = '127.0.0.1'

c.NotebookApp.open_browser = True

這兩個去除注釋,監聽本機埠地址 127.0.0.1 即可。

 3   配置虛擬環境到 jupyter 內

用 python -m ipykernel install --user --name 虛擬環境名 --display-name Jupyter中要顯示的名字,來綁定已有的虛擬環境。

python -m ipykernel install 
python -m ipykernel install
python -m ipykernel install
python -m ipykernel install 
python -m ipykernel install 

 4   啟動 notebook,切換不同的環境

菜單裡 服務 -> 改變服務 -> 列出了所有的虛擬環境。

 1   克隆官方示例

git clone https://github.com/tensorflow/examples --depth 1

 2   圖像分類應用

首先安裝依賴包,再下載一個 MobileNet 模型文件和分類標籤文件到 tmp 目錄中。

cd examples/lite/examples/image_classification/raspberry_pibash download.sh /tmp

 3   在 notebook 中運行一下推理

我們新建一個 classify_picamera.ipynb 文件,讀入tflite模型,
labels = load_labels('/tmp/labels_mobilenet_quant_v1_224.txt')interpreter = Interpreter('/tmp/mobilenet_v1_1.0_224_quant.tflite')interpreter.allocate_tensors()_, height, width, _ = interpreter.get_input_details()[0]['shape']

調用 interpreter.invoke() 來推理,
def classify_image(interpreter, image, top_k=1):  """Returns a sorted array of classification results."""  set_input_tensor(interpreter, image)  interpreter.invoke()  output_details = interpreter.get_output_details()[0]  output = np.squeeze(interpreter.get_tensor(output_details['index']))
# If the model is quantized (uint8 data), then dequantize the results if output_details['dtype'] == np.uint8: scale, zero_point = output_details['quantization'] output = scale * (output - zero_point)
ordered = np.argpartition(-output, top_k) return [(i, output[i]) for i in ordered[:top_k]]

最後在 opencv 的窗口來展示一下分類結果。

with picamera.PiCamera(resolution=(640, 480), framerate=30) as camera:    camera.start_preview()    try:      stream = io.BytesIO()      for _ in camera.capture_continuous(          stream, format='jpeg', use_video_port=True):        stream.seek(0)        image = Image.open(stream).convert('RGB').resize((width, height),                                                         Image.ANTIALIAS)        start_time = time.time()        results = classify_image(interpreter, image)                elapsed_ms = (time.time() - start_time) * 1000        label_id, prob = results[0]                camera.annotate_text = '%s %.2f\n%.1fms' % (labels[label_id], prob,                                                    elapsed_ms)                data = np.frombuffer(stream.getvalue(), dtype=np.uint8)        dst = cv2.imdecode(data, cv2.IMREAD_UNCHANGED)        cv2.imshow("img", dst)        stream.seek(0)        stream.truncate(0)                if(cv2.waitKey(1) == ord('q')):            cv2.destroyAllWindows()            break            finally:      camera.stop_preview()      print('end')

速度還是比較快的,130ms一幀,能達到大約是7-8fps,準確率也很高,可見提升還是很明顯的。這既得益於 MobileNet 的小巧,也得益於 tflite 的精簡模型的加速,可達到準實時的效果。

 2   目標檢測應用

cd examples/lite/examples/object_detection/raspberry_pibash download.sh /tmp

下載一個 MobileNet ssd v2 模型文件和 coco 標籤文件到 tmp 目錄中。

 3   在 notebook 中運行一下推理

我們新建一個 detect_picamera.ipynb 文件,讀入tflite模型,
labels = load_labels('/tmp/coco_labels.txt')interpreter = Interpreter('/tmp/detect.tflite')interpreter.allocate_tensors()_, input_height, input_width, _ = interpreter.get_input_details()[0]['shape']

調用 interpreter.invoke() 來推理,
def detect_objects(interpreter, image, threshold):  """Returns a list of detection results, each a dictionary of object info."""  set_input_tensor(interpreter, image)  interpreter.invoke()
boxes = get_output_tensor(interpreter, 0) classes = get_output_tensor(interpreter, 1) scores = get_output_tensor(interpreter, 2) count = int(get_output_tensor(interpreter, 3))
results = [] for i in range(count): if scores[i] >= threshold: result = { 'bounding_box': boxes[i], 'class_id': classes[i], 'score': scores[i] } results.append(result) return results

獲得標註目標,轉換標註框和類別標籤

def annotate_objects(annotator, results, labels):  """Draws the bounding box and label for each object in the results."""  for obj in results:            ymin, xmin, ymax, xmax = obj['bounding_box']    xmin = int(xmin * CAMERA_WIDTH)    xmax = int(xmax * CAMERA_WIDTH)    ymin = int(ymin * CAMERA_HEIGHT)    ymax = int(ymax * CAMERA_HEIGHT)
annotator.bounding_box([xmin, ymin, xmax, ymax]) annotator.text([xmin, ymin], '%s\n%.2f' % (labels[obj['class_id']], obj['score']))

最後用 opencv 合併一下視頻流和標註層,在 cv2 窗口展示。

with picamera.PiCamera(    resolution=(CAMERA_WIDTH, CAMERA_HEIGHT), framerate=30) as camera:  camera.start_preview()  try:    stream = io.BytesIO()    annotator = Annotator(camera)    for _ in camera.capture_continuous(        stream, format='jpeg', use_video_port=True):      stream.seek(0)      image = Image.open(stream).convert('RGB').resize(          (input_width, input_height), Image.ANTIALIAS)      start_time = time.monotonic()      results = detect_objects(interpreter, image, 0.4)      elapsed_ms = (time.monotonic() - start_time) * 1000
annotator.clear() annotate_objects(annotator, results, labels) annotator.text([5, 0], '%.1fms' % (elapsed_ms)) annotator.update() data = np.frombuffer(stream.getvalue(), dtype=np.uint8) dst = cv2.imdecode(data, cv2.IMREAD_UNCHANGED) dst2 = cv2.cvtColor(np.asarray(annotator._buffer),cv2.COLOR_RGB2BGR) dst = cv2.add(dst, dst2) cv2.imshow("img", dst) stream.seek(0) stream.truncate(0) if(cv2.waitKey(1) == ord('q')): cv2.destroyAllWindows() break
finally: camera.stop_preview()

180-200ms一幀,5 fps左右,工作量上升了些,所以比分類任務稍慢了一些,這應該已達到樹莓派 4代的極限。若要再提升性能,就要用上 intel 神經榜或 google coral 這類 usb 擴展資源了。

下一篇

我們將在 tersorflow lite 上

做一些有趣的應用,

敬請期待...

相關焦點

  • 用樹莓派4b構建深度學習應用(一)硬體篇
    4b構建深度學習應用 14個內容
  • 用樹莓派4b構建深度學習應用(十二)口罩篇
    上一篇我們把環境和網絡問題都解決了,這一篇在 COVID-19 仍在全世界肆虐的當下,我們嘗試用 AI 來做一個有趣的自動戴口罩應用。
  • 用樹莓派4b構建深度學習應用(二)軟體篇
    上回把硬體都準備好了,這篇我們來搭建一下樹莓派的系統,並安裝一些必要的工具軟體。
  • TensorFlow Lite 微控制器
    註:構建和轉換模型 連結https://tensorflow.google.cn/lite/microcontrollers/build_convert#%E8%BD%AC%E6%8D%A2%E6%A8%A1%E5%9E%8B理解 C++ 庫 連結https://tensorflow.google.cn/lite/microcontrollers
  • 從今天起,TensorFlow 1.9開始支持樹莓派了
    銅靈 發自 凹非寺量子位 出品 | 公眾號 QbitAI幾個小時前,TensorFlow正式宣布TensorFlow 1.9開始支持樹莓派了
  • 谷歌移動端深度學習框架TensorFlow Lite正式發布
    項目連結:https://github.com/tensorflow/tensorflow/tree/master/tensorflow/contrib/lite設計初衷:輕量級:允許小 binary size 和快速初始化/啟動的設備端機器學習模型進行推斷。跨平臺:運行時的設計使其可以在不同的平臺上運行,最先允許的平臺是安卓和 iOS。
  • 社區分享 | TensorFlow Lite C++ API 開源案例教程
    因此,我們這個項目採用 Bazel 作為構建工具,方便 TensorFlow Lite 與 OpenCV 等第三方庫的代碼版本管理。首先,我們一起了解一下如何用 Bazel 構建 C++ 項目。設置構建環境在構建項目之前,我們需要設置項目的構建環境 (Workspace)。
  • 谷歌第一個TensorFlow中文教程發布!深度解析TensorFlow Lite
    )作者 :Renmin Gu【新智元導讀】本期來自 Google 的工程師 Renmin 為大家帶來 TensorFlow Lite 的深度解析視頻,主要講述 TensorFlow Lite 模型文件格式,並可視化以幫助大家記憶理解,也包含 TensorFlow Lite 的具體加載運行過程
  • 基於TensorFlow的深度學習實戰
    毫不誇張得說,TensorFlow的流行讓深度學習門檻變得越來越低,只要你有Python和機器學習基礎,入門和使用神經網絡模型變得非常簡單。TensorFlow簡介如前所述,TensorFlow是一個深度學習庫,使用這一框架,可以用來構建和測試深度神經網絡。深度學習讓我們能夠以極高的準確性構建複雜的應用程式。
  • TensorFlow Lite 助力產品落地
    我們很高興地發布 TensorFlow Lite Model Maker,這款工具簡單易用。通過遷移學習,您可在您的數據集上應用前沿的機器學習模型。此工具將複雜的機器學習概念封裝在直觀的 API 中,無需機器學習專業知識,您也可以開啟機器學習之旅。
  • TensorFlow Lite 深度解析 | 中文教學視頻
    本期來自 Google 的工程師 Renmin 為大家帶來 TensorFlow Lite 的深度解析視頻,主要講述 TensorFlow Lite 模型文件格式,並可視化以幫助大家記憶理解,也包含 TensorFlow Lite 的具體加載運行過程,並給出關鍵的數據結構描述,同樣以可視化的形式呈現給大家。
  • 零基礎學習樹莓派_樹莓派4b安裝OpenCV4.4
    樹莓派學習筆記公眾號搜索--樹莓派OpenCV學舍
  • Tensorflow 2.0到底好在哪裡?
    更多優質內容請關注微信公眾號「AI 前線」(ID:ai-front) 如今已經沒有人質疑機器學習和深度學習的重要性了。數十年來這一行業讓人們見識過無數承諾、騙局和失望,時至今日兩大技術終於帶來了眾多實際應用。機器學習或深度學習應用離充分完善還有很長的路要走,但現有的成果已經非常喜人了。
  • 【免費教學】Tensorflow Lite極簡入門
    Lite在行動裝置上的應用,讓我們的設備智能起來。在訓練學習的過程中,Checkpoint 文件記錄了不同的 Iteration 中變量的取值。Frozen Graph用 Graph Def 和 Checkpoint 生成 Frozen Graph 的過程叫做「冷凍」。為什麼稱之為冷凍呢?
  • 有道雲筆記是如何使用TensorFlow Lite的?
    在 Android 上,我們可以使用 bazel 構建工具進行編譯。bazel 工具的安裝和配置就不再贅述了,有過 TensorFlow 編譯經驗的同學應該都熟悉。如果只想編譯庫文件,可以編譯 "//tensorflow/contrib/lite/java:tensorflowlite" 這個 target,得到的是 libtensorflowlite_jni.so 庫和相應的 java 層接口。
  • 學習教程 | 使用 TensorFlow Lite 在 Android App 中生成超分圖片
    在這篇文章中,我們將使用 TFLite C API,因為有許多的開發者表示希望我們能提供這樣一個範例。file_path=org%2Ftensorflow%2Ftensorflow-lite%2F2.3.0%2Ftensorflow-lite-2.3.0.aar" dest "${project.rootDir}/libraries/tensorflow-lite-2.3.0.aar" overwrite false retries 5
  • 教程 | 如何用TensorFlow在安卓設備上實現深度學習推斷
    她在 Insight 工作的時候,在安卓系統上用 TensorFlow 部署了一個 WaveNet 模型。本文詳細介紹了部署和實現過程。對於個人和公司來說,存在許多狀況是更希望在本地設備上做深度學習推斷的:想像一下當你在旅行途中沒有可靠的網際網路連結時,或是要處理傳輸數據到雲服務的隱私問題和延遲問題時。
  • 玩轉TensorFlow Lite:有道雲筆記實操案例分享
    在 Android 上,我們可以使用 bazel 構建工具進行編譯。bazel 工具的安裝和配置就不再贅述了,有過 TensorFlow 編譯經驗的同學應該都熟悉。如果只想編譯庫文件,可以編譯 "//tensorflow/contrib/lite/java:tensorflowlite" 這個 target,得到的是 libtensorflowlite_jni.so 庫和相應的 java 層接口。
  • 【免費教學】在嵌入式中使用 TensorFlow Lite
    今天與大家分享 Android 平臺上的一些 TensorFlow Lite 應用,先來一起看看視頻吧:TensorFlow Lite 在安卓中的應用 視頻中的 App 用了一個叫 MobileNet 的模型。這個模型的特點是體積小、速度快(延遲低)、能耗低。
  • TensorFlow Lite 轉換器中的 TensorFlow 算子融合
    >https://colab.sandbox.google.com/github/tensorflow/tensorflow/blob/master/tensorflow/lite/examples/experimental_new_converter/Keras_LSTM_fusion_Codelab.ipynb此外,我們通過提供連接至基礎架構轉換的便捷接口,實現了到其他任意 TensorFlow