易 AI - 使用 TensorFlow Object Detection API 訓練自定義目標檢測模型

原文:https://makeoptim.com/deep-learning/yiai-object-detection

前言

本文將介紹目標檢測(Object Detection)的概念,並通過案例講解如何使用 TensorFlow Object Detection API 來訓練自定義的目標檢測器,包括:數據集採集和製作TensorFlow Object Detection API 安裝以及模型的訓練

案例效果如下圖所示:

目標檢測

如上圖所示,圖像分類解決的問題是圖中的物體是什麼,而目標檢測能識別圖片中有哪些物體以及物體的位置(座標)

位置

目標檢測的位置信息一般有兩種格式:

  • 極座標(xmin, ymin, xmax, ymax):
    • xmin,ymin:x,y 座標的最小值
    • xmin,ymin:x,y 座標的最大值
  • 中心點:(x_center, y_center, w, h)
    • x_center, y_center:目標檢測框的中心點座標
    • w,h:目標檢測框的寬、高

注:圖片左上角爲原點(0,0)

發展史

傳統方法(候選區域+手工特徵提取+分類器)

HOG+SVM、DPM

Region Proposal+CNN(Two-stage)

R-CNN, SPP-NET, Fast R-CNN, Faster R-CNN

端到端(One-stage)

YOLO、SSD

TensorFlow Object Detection API

TensorFlow Object Detection API 是一個構建在 TensorFlow 之上的開源框架,可以輕鬆構建、訓練和部署對象檢測模型。另外,TensorFlow Object Detection API 還提供了 Model Zoo 方便我們選擇切換預訓練模型

安裝依賴項

使用以下命令檢查是否安裝成功。

$ conda --version
conda 4.9.2
$ protoc --version
libprotoc 3.17.1

安裝 API

TensorFlow Object Detection API 官方的安裝步驟較爲繁瑣,筆者寫了一個腳本直接一鍵安裝。

執行 git clone https://github.com/CatchZeng/object-detection-api.git 下載倉庫,然後到該倉庫(下文簡稱 oda 倉庫)目錄下,執行以下命令,如果看到如下輸出,表示安裝成功。

$ conda create -n  od python=3.8.5 && conda activate od && make install
......
----------------------------------------------------------------------
Ran 24 tests in 21.869s

OK (skipped=1)

注:如果你不想用 conda,可以在自己的 python 環境上直接使用 make install 安裝即可,比如在 colab 中使用。

注:由於 cudaDNNtoolkit 更新可能沒有 TensorFlow 快。因此,如果你的機器有 GPU,安裝完成後,需要將 TensorFlow 降回到 cudaDNNtoolkit 支持的版本這樣才能支持 GPU 訓練,以 2.4.1 爲例:

$ pip install --upgrade tf-models-official==2.4.0
$ pip install --upgrade tensorflow==2.4.1

注:如果安裝失敗,可以參考官方文檔的詳細步驟安裝。

工程創建

注:!!! 從這裏開始,請確保在 conda od 的環境下執行。

$ conda activate od
$ conda env list
# conda environments:
#
od                    *  /Users/catchzeng/.conda/envs/od
tensorflow               /Users/catchzeng/.conda/envs/tensorflow
base                     /Users/catchzeng/miniconda3

oda 倉庫目錄下,執行以下命令,創建工程目錄結構。

注:SAVE_DIR 爲保存項目的目錄,NAME 爲項目的名稱。

$ make workspace-box SAVE_DIR=workspace NAME=test
└── workspace
    └── test
        ├── Makefile
        ├── annotations:存放標註好的數據集數據(val.record、train.record、label_map.pbtxt)
        ├── convert_quant_lite.py:量化 tflite 模型腳本
        ├── export_tflite_graph_tf2.py:導出 tflite 模型腳本
        ├── exported-models:存放訓練完之後導出的模型
        ├── exporter_main_v2.py:導出模型腳本
        ├── images:數據集圖片和 xml 標註
        │   ├── test:手動驗證圖片
        │   ├── train:訓練集圖片和 xml 標註
        │   └── val:驗證集圖片和 xml 標註
        ├── model_main_tf2.py:訓練模型腳本
        ├── models:自定義模型
        ├── pre-trained-models:TensorFlow Model Zoo 提供的預訓練模型
        └── test_images.py:手動驗證圖片腳本

數據集

圖片

筆者喜歡喝茶,這次就用茶杯(cup)、茶壺(teapot)、加溼器(humidifier) 來做案例吧。

將收集的圖片,放入工程目錄的 images 的三個子目錄下。

注:本案例只是爲了驗證如何訓練目標識別模型,因此數據集採集得比較少,實際項目中記得儘量採集多點數據集

標註

收集完圖片後,需要對訓練驗證集圖片進行標註。標註工具,選用較爲常用的 LabelImg

根據 installation 的說明安裝好 LabelImg,然後執行 labelImg 選擇 trainval 文件夾進行標註。

標註完成後,會生成圖片對應的 xml 標註文件,如下所示:

workspace/test/images
├── test
│   ├── 15.jpg
│   └── 16.jpg
├── train
│   ├── 1.jpg
│   ├── 1.xml
│   ├── 10.jpg
│   ├── 10.xml
│   ├── 2.jpg
│   ├── 2.xml
│   ├── 3.jpg
│   ├── 3.xml
│   ├── 4.jpg
│   ├── 4.xml
│   ├── 5.jpg
│   ├── 5.xml
│   ├── 6.jpg
│   ├── 6.xml
│   ├── 7.jpg
│   ├── 7.xml
│   ├── 8.jpg
│   ├── 8.xml
│   ├── 9.jpg
│   └── 9.xml
└── val
    ├── 11.jpg
    ├── 11.xml
    ├── 12.jpg
    ├── 12.xml
    ├── 13.jpg
    ├── 13.xml
    ├── 14.jpg
    └── 14.xml

LabelMap

workspace/test/annotations 文件夾下創建 label_map.pbtxt,內容爲模型需要識別的目標。

item {
    id: 1
    name: 'cup'
}

item {
    id: 2
    name: 'teapot'
}

item {
    id: 3
    name: 'humidifier'
}

創建 TFRecord

TensorFlow Object Detection API 只支持 TFRecord 格式的數據集,因此,需要把標註好的數據集進行轉換。

cd 到工程目錄(cd workspace/test),然後執行 make gen-tfrecord,將在 annotations 文件夾下生成 TFRecord 格式的數據集。

$ make gen-tfrecord
python ../../scripts/preprocessing/generate_tfrecord.py \
        -x images/train \
        -l annotations/label_map.pbtxt \
        -o annotations/train.record
Successfully created the TFRecord file: annotations/train.record
python ../../scripts/preprocessing/generate_tfrecord.py \
        -x images/val \
        -l annotations/label_map.pbtxt \
        -o annotations/val.record
Successfully created the TFRecord file: annotations/val.record
annotations
├── label_map.pbtxt
├── train.record
└── val.record

模型訓練

注:!!! 從這裏開始,請確保已經 cd 到工程目錄(cd workspace/test)。

下載預訓練模型

Model Zoo 中選擇合適的模型下載解壓並放到 workspace/test/pre-trained-models 中。

如果你選擇的是 SSD MobileNet V2 FPNLite 320x320 可以執行如下命令,自動下載並解壓

$ make dl-model

目錄結構如下:

└── test
    └── pre-trained-models
        └── ssd_mobilenet_v2_fpnlite_320x320_coco17_tpu-8
            ├── checkpoint
            ├── pipeline.config
            └── saved_model

配置訓練 Pipeline

models 目錄創建對應的模型文件夾,比如:ssd_mobilenet_v2_fpnlite_320x320,並拷貝 pre-trained-models/ssd_mobilenet_v2_fpnlite_320x320_coco17_tpu-8/pipeline.config

└── test
    ├── models
    │   └── ssd_mobilenet_v2_fpnlite_320x320
    │       └── pipeline.config
    └── pre-trained-models

其中,pipeline.config 如下幾處需要根據項目修改

model {
  ssd {
    num_classes: 3 # 修改爲需要識別的目標個數,示例項目爲 3 種
    ......
}
train_config {
  batch_size: 8 # 這裏需要根據自己的配置,調整大小,這裏設置爲 8
  ......
  optimizer {
    momentum_optimizer {
      learning_rate {
        cosine_decay_learning_rate {
          learning_rate_base: 0.07999999821186066
          total_steps: 10000 # 修改爲想要訓練的總步數
          warmup_learning_rate: 0.026666000485420227
          warmup_steps: 1000
        }
      }
      momentum_optimizer_value: 0.8999999761581421
    }
    use_moving_average: false
  }
  fine_tune_checkpoint: "pre-trained-models/ssd_mobilenet_v2_fpnlite_320x320_coco17_tpu-8/checkpoint/ckpt-0" # 修改爲預製模型的路徑
  num_steps: 10000 # 修改爲想要訓練的總步數
  startup_delay_steps: 0.0
  replicas_to_aggregate: 8
  max_number_of_boxes: 100
  unpad_groundtruth_tensors: false
  fine_tune_checkpoint_type: "detection" # 這裏需要修改爲 detection,因爲我們是做目標檢測
  fine_tune_checkpoint_version: V2
}
train_input_reader {
  label_map_path: "annotations/label_map.pbtxt" # 修改爲標註的路徑
  tf_record_input_reader {
    input_path: "annotations/train.record" # 修改爲訓練集的路徑
  }
}
eval_config {
  metrics_set: "coco_detection_metrics"
  use_moving_averages: false
}
eval_input_reader {
  label_map_path: "annotations/label_map.pbtxt" # 修改爲標註的路徑
  shuffle: false
  num_epochs: 1
  tf_record_input_reader {
    input_path: "annotations/val.record" # 修改爲驗證集的路徑
  }
}

訓練模型

$ make train

注:如遇以下問題

ValueError: numpy.ndarray size changed, may indicate binary incompatibility. Expected 88 from C header, got 80 from PyObject

執行以下命令,重新安裝下 numpy 即可。

pip uninstall numpy
pip install numpy

模型導出與轉換

  • 普通模型

    $ make export
    
  • TFLite 模型

    $ make export-lite
    
  • 轉換 TFLite 模型

    $ make convert-lite
    
  • 轉換量化版 TFLite 模型

    $ make convert-quant-lite
    

注:以上命令,大家可以加 -640 表示使用 SSD MobileNet V2 FPNLite 640x640 的模型,比如:make train -> make train-640

測試模型

執行 make export 導出模型後,將測試圖片放到 images/test 文件夾下,然後執行 python test_images.py 即可輸出標記好目標的圖片到 images/test_annotated

小結

本文通過案例將目標檢測的整個流程都過了一遍,希望能幫助大家快速掌握訓練自定義目標檢測器的能力。

案例的代碼和數據集都已經放在了 https://github.com/CatchZeng/object-detection-api,有需要的同學可以自行獲取。

後面的文章將會爲大家帶來,目標檢測的原理常用的目標檢測網絡,以及目標分割。本篇就到這了,咱們下一篇見。

參考鏈接

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