Tensorflow Lite -- camera demo


簡介

TF lite是Tensorflow官方提供的在移動設備運行機器學習模型的解決方案。

主要優點:

  • 性能(沒有明顯的准確率的下降)
  • 低延遲
  • 模型體積小
  • 兼容性(安卓,ios)

camera demo是官方提供的例子。通過攝像頭實時的影像,根據已訓練好的模型,判斷出當前鏡頭里的物品分類。

參考:https://codelabs.developers.google.com/codelabs/tensorflow-for-poets-2-ios/#2

 

下面列舉幾個關鍵的點

數據

  • .tflite文件:mobilenet_v1_1.0_224.tflite (在ImageNet上用Mobilenet訓練出的模型,flatbuffer格式)
  • labels: labels.txt (對應的所有標簽)
 
.tflite文件其實是個FlatBuffer文件。 FlatBuffer的優點和ProtoBuffer的比較
一般的圖模型文件是.pb文件(Protocol Buffer)保存,tflite文件就是通過pb文件轉換過來的。同時做了一些優化:
  • 去掉了沒有用到的圖節點(因為TFLite不需要訓練,)
  • 通過連接操作成為更有效的組合操作,從而提高性能。
 
TF的源碼中專門有個python腳本用於轉換:
⁨tensorflow⁩/tensorflow⁩/⁨lite⁩/⁨python⁩/tflite_convert.py
 
使用方式:
  • graph_def_file,  pb文件
  • output_file,   輸出tflite文件
  • input_format,    輸入文件的格式
    • TENSORFLOW_GRAPHDEF, graphdef
  • output_format
    • TFLITE, 上面提到的tflite格式
  • input_shape, 一個圖片的維度 (1,image_size, image_size, 3), 3是通道數
  • input_array,
  • output_array
  • inference_type  
  • input_data_type
IMAGE_SIZE=224
tflite_convert \
  --graph_def_file=tf_files/retrained_graph.pb \
  --output_file=tf_files/optimized_graph.lite \
  --input_format=TENSORFLOW_GRAPHDEF \
  --output_format=TFLITE \
  --input_shape=1,${IMAGE_SIZE},${IMAGE_SIZE},3 \
  --input_array=input \
  --output_array=final_result \
  --inference_type=FLOAT \
  --input_data_type=FLOAT
 
 
關鍵方法
 
1、讀取tflite文件
  tflite::FlatBufferModel::BuildFromFile(), 返回類型 std::unique_ptr<tflite::FlatBufferModel>,讀取的就是tflite文件。
2、讀取label文件
  按行讀取到vector中。
3、運行model
  • 基於FlatBufferModel構建Interperter
  • tflite::ops::builtin::BuiltinOpResolver resolver;
    tflite::InterpreterBuilder(*model, resolver)(&interpreter); // model就是FlatBufferModel

     

  • resize input tensors (Interperter->ResizeInputTensor(),重定義大小后,要調用AllocateTensors方法,更新tensors。但這個操作比較費時,在size不變的情況下,不要調用。)
  • int input = interpreter->inputs()[0];
    std::vector<int> sizes = {1, 224, 224, 3};
    interpreter->ResizeInputTensor(input, sizes);

     

  • 設置input tensor的值
  • // 取輸入tensor
    float* out = interpreter->typed_tensor<float>(input);
    ProcessInputWithFloatModel(in, out, image_width, image_height, image_channels);
    
    // 向輸入tensor的原始數據中填充 像素值。像素值經過標准化。
    void ProcessInputWithFloatModel(
        uint8_t* input, float* buffer, int image_width, int image_height, int image_channels) {
      for (int y = 0; y < wanted_input_height; ++y) {
        float* out_row = buffer + (y * wanted_input_width * wanted_input_channels);
        for (int x = 0; x < wanted_input_width; ++x) {
          const int in_x = (y * image_width) / wanted_input_width;
          const int in_y = (x * image_height) / wanted_input_height;
          uint8_t* input_pixel =
              input + (in_y * image_width * image_channels) + (in_x * image_channels);
          float* out_pixel = out_row + (x * wanted_input_channels);
          for (int c = 0; c < wanted_input_channels; ++c) {
            out_pixel[c] = (input_pixel[c] - input_mean) / input_std;
          }
        }
      }
    }

     

  • invoke,執行模型,得到的結果保存在輸出張量里。
  • if (interpreter->Invoke() != kTfLiteOk) {
        LOG(FATAL) << "Failed to invoke!";
    }
  • 讀取output tensor的值
  • uint8_t* quantized_output = interpreter->typed_output_tensor<uint8_t>(0);
  • 取超過閾值的topN個預測值
  • GetTopN(output, output_size, kNumResults, kThreshold, &top_results);

     

關鍵類
 
  • FlatBufferModel, 模型類
  • Interperter,解釋器類
  • TfLiteTensor, Tensor類
 
Interperter類中,跟輸入輸出張量相關的方法:
 
// Tensors被定義為整型。
const std::vector<int>& inputs() const; // 所有輸入張量對應的索引
const std::vector<int>& outputs() const; // 所有輸出張量對應的索引
TfLiteTensor* tensor(int tensor_index); // 返回對應索引的tensor
 
template<class T> T* typed_tensor(int tensor_index); //取得指定tensor的原始數據的指針 T* typed_input_tensor(int index); //取得輸入tensor T* typed_output_tensor(int index); // 取得輸出tensor
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM