一. 概述
前幾篇文章,說明了如何搭建 Tensorflow Keras 1.x / 2.x / Keras 環境,同時也引入相對應的運算概念並帶領各位建立手寫辨識系統。接下來,將一步步引導各位,將所建立的手寫辨識模組在 i.MX8 的平台實現!! 主要以 i.MX8QM 與 i.MX8M Plus 為主。事不宜遲,啟用你的開發板一起動手體驗吧!! 如下圖所示,為系列博文之示意架構圖。此架構圖隸屬於 i.MX8M Plus 的方案博文中,並屬於 eIQ 機器學習開發環境 內的 推理引擎層(Inference Engines Layer) 的子系列 !! 目前章節介紹 “i.MX8 平台實現 !! Tensorflow Lite 手寫識別”!!
若新讀者欲理解人工智慧、機器學習以及深度學習的差異,可點選查閱下方博文
大大通精彩博文 探討機器學習與深度學習之差異
TFlite 系列博文 - 文章架構示意圖 (1)
TFlite 系列博文 - 文章架構示意圖 (2)
二. NXP i.MX8 手寫識別實現
使用搭建環境 : Python 3.6 + Windows 10 + Tensorflow 2.1.0 + Keras 2.3.1
硬體平台環境 : Yocto BSP 5.4.47-2.2.0 + PyeIQ 2.0
本節將拆分為三個步驟介紹,首先第一步介紹如何儲存模組、第二步須將模組轉成 Tensorflow Lite 的模組格式、第三步建立手寫辨識之推理代碼並進行實現。
(1) Tensorflow & Keras 模組儲存 :
延續 【ATU Book-i.MX8系列 - TFLite】Tensorflow 2. x 建立手寫識別 或 Tensorflow Keras 建立手寫識別 章節的應用。若尚未查看的讀者,請至該文章查看如何建立手寫識別模型。
很可惜 !! Tensorflow 1.x 所轉換後的模組並非能直接應用於 i.MX8 平台上故暫不介紹。
Tensorflow 2.x 儲存模組之方式 :
在訓練完成模組後,即可存儲模組,並在對應的資料夾下請確認是否儲存成功。
tf.saved_model.save(model, "Tensorflow_2_HandWrite")
Tensorflow Keras 儲存模組之方式 :
在訓練完成模組後,即可存儲模組,並在對應的資料夾下請確認是否儲存成功。
model. save('tf2_keras_handwrite.h5')
(2) Tensorflow Lite 模組轉換 :
這裡將使用 Tensorflow 2.x 所提供的轉換工具 – Tensorflow Lite Convert 來進行模組轉換。並建議採用 Python 撰寫的方式,而非用指令列工具進行轉換,這能夠完善優化與最佳化其模組。
Tensorflow 2.x 轉 Tensorflow Lite 代碼 :
Tensorflow Lite Convert使用方式 : https://www.tensorflow.org/lite/convert?hl=zh-tw
#---------------------------------------------------------------------------------------------------------------
# 轉成 Tensorflow Lite
#---------------------------------------------------------------------------------------------------------------
import tensorflow as tf
import numpy as np
def representative_dataset_gen():
for _ in range(250):
yield [np.random.uniform(0.0, 1.0, size=(1, 28, 28, 1)).astype(np.float32)] #需要輸入端大小
converter = tf.lite.TFLiteConverter.from_saved_model("Tensorflow_2_HandWrite")
converter.optimizations = [tf.lite.Optimize.DEFAULT]
converter.target_spec.supported_ops = [tf.lite.OpsSet.TFLITE_BUILTINS_INT8]
converter.inference_input_type = tf.uint8
converter.inference_output_type = tf.uint8
converter.representative_dataset = representative_dataset_gen
tflite_model = converter.convert()
with open('tf2_handwrite_model_qunat_uint8.tflite','wb') as f:
f.write(tflite_model)
轉換成功後,即會顯示以下訊息
在對應的資料夾下請確認是否轉換成功
Tensorflow keras 轉 Tensorflow Lite 代碼 :
#---------------------------------------------------------------------------------------------------------------
# 轉成 Tensorflow Lite
#---------------------------------------------------------------------------------------------------------------
import tensorflow as tf
import numpy as np
def representative_dataset_gen():
for _ in range(250):
yield [np.random.uniform(0.0, 1.0, size=(1, 28, 28, 1)).astype(np.float32)] #需要輸入端大小
converter = tf.compat.v1.lite.TFLiteConverter.from_keras_model_file('tf2_keras_handwrite.h5')
converter.optimizations = [tf.lite.Optimize.DEFAULT]
converter.target_spec.supported_ops = [tf.lite.OpsSet.TFLITE_BUILTINS_INT8]
converter.inference_input_type = tf.uint8
converter.inference_output_type = tf.uint8
converter.representative_dataset = representative_dataset_gen
tflite_model = converter.convert()
with open('tf2_handwrite_model_qunat_uint8.tflite','wb') as f:
f.write(tflite_model)
轉換成功後,即會顯示以下訊息
在對應的資料夾下請確認是否轉換成功
(3) 建立手寫辨識之推理代碼 :
建立手寫辨識之推理代碼後,即可嘗試運用此代碼在 i.MX8 平台上實現手寫識別。
建立推理代碼 :
import os
import argparse
import cv2
import numpy as np
import sys
import time
import importlib.util
from tflite_runtime.interpreter import Interpreter
from tflite_runtime.interpreter import load_delegate
#取得終端機之輸入資訊
def get_cmd():
parser = argparse.ArgumentParser()
parser.add_argument('--image', help='path to file image', required=True)
parser.add_argument('--model', help='Path to tflite model.', required=True)
return parser.parse_args()
#主要程序
def main():
args = get_cmd() #讀取終端機提供的資訊
interpreter = Interpreter(args.model)
interpreter.allocate_tensors() #讀取模型架構資訊 Get model graph details
input_details = interpreter.get_input_details()
output_details = interpreter.get_output_details()
width = input_details[0]['shape'][2]
height = input_details[0]['shape'][1]
# 讀取影像與處理成輸入張量
frame = cv2.imread(args.image)
image_height,image_width=frame.shape[:2]
frame_counter = 0
start = time.time()
frame_counter += 1
frame_gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
frame_resized = cv2.resize(frame_gray, (width, height))
input_data = np.expand_dims(frame_resized, axis=0)
input_data = np.expand_dims(input_data, axis=3)
interpreter.set_tensor(input_details[0]['index'], input_data) # set frame as input tensors
interpreter.invoke()# perform inference
# 定義輸出張量
classes = interpreter.get_tensor(output_details[0]['index'])[0]
prob_max_num = np.where(classes==classes.max())[0]
print(prob_max_num)
if __name__ == "__main__":
main()
將代碼傳送至 i.MX8MPLUS 開發板上 :
$ scp example.py root@xx.xx.xx.xx:~
開啟 i.MX8MPLUS 開發板運行指令 :
$ python3 tflite_cv.py --image mnist_1.bmp --model tf2_handwrite_model_qunat_uint8.tflite
完整代碼連結 : 請點選
三. 結語
經由上述實作,相信各位已經成功的在 i.MX8 的平台上,並執行成功此範例程式且如同預期預測到數字 1 的結果 !! 若是要實作其他模組或應用,僅需要更換模組與輸入/輸出端方式即可。未來亦可在範例代碼加入顯示方式,讓顯示更加完善 !! 換句話說,就是僅需要掌握 Python 與 Tensorflow Lite Runtime 推理引擎這兩大重點,即能夠靈活應用 !! 未來將介紹更多體驗輕量化網路與深度學習的應用介紹!! 敬請期待 !!
四. 參考文件
[1] ITREAD - 從0.1到2.0一文看盡TensorFlow奮鬥史
[2] 軟體之心 - 包裝再升級?Tensorflow 2.0的重大改變
[3] WiKi - Keras開源神經網路庫
[4] 科技報橘 - 手機上的輕量版 AI 運算,TensorFlow Lite 問世!
[5] Anaconda - 官方網站
[6] Tensorflow – 官方網站
[7] 深智數位 – Tensorflow 1.x/2.x 完整工程實作
[8] 軟體之心 - 包裝再升級?Tensorflow 2.0的重大改變
[9] iT1邦幫忙 - Tensorflow 的 Eager Mode
[10] 軟體之心 - Keras 手寫辨識 MNIST
如有任何相關 Tensorflow Lite 技術問題,歡迎至博文底下留言提問 !!
接下來還會分享更多 Tensorflow Lite 的技術文章 !!敬請期待 【ATU Book-i.MX8 系列 - TFLite】 !!
評論