【ATU Book-i.MX8系列 - TFLite】 i.MX8 平台實現 !! Tensorflow Lite 手寫識別

一.   概述

前幾篇文章,說明了如何搭建 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
 !!

★博文內容均由個人提供,與平台無關,如有違法或侵權,請與網站管理員聯繫。

★文明上網,請理性發言。內容一周內被舉報5次,發文人進小黑屋喔~

評論