易 AI - 使用 TensorFlow Object Detection API 訓(xùn)練自定義目標(biāo)檢測(cè)模型

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

前言

本文將介紹目標(biāo)檢測(cè)(Object Detection)的概念漠吻,并通過案例講解如何使用 TensorFlow Object Detection API 來訓(xùn)練自定義的目標(biāo)檢測(cè)器吃引,包括:數(shù)據(jù)集采集和制作TensorFlow Object Detection API 安裝以及模型的訓(xùn)練闷游。

案例效果如下圖所示:

image

目標(biāo)檢測(cè)

image

如上圖所示拜姿,圖像分類解決的問題是圖中的物體是什么烙样,而目標(biāo)檢測(cè)能識(shí)別圖片中有哪些物體以及物體的位置(坐標(biāo))

位置

目標(biāo)檢測(cè)的位置信息一般有兩種格式:

  • 極坐標(biāo)(xmin, ymin, xmax, ymax):
    • xmin,ymin:x,y 坐標(biāo)的最小值
    • xmin,ymin:x,y 坐標(biāo)的最大值
  • 中心點(diǎn):(x_center, y_center, w, h)
    • x_center, y_center:目標(biāo)檢測(cè)框的中心點(diǎn)坐標(biāo)
    • w,h:目標(biāo)檢測(cè)框的寬蕊肥、高

注:圖片左上角為原點(diǎn)(0,0)

發(fā)展史

image

傳統(tǒng)方法(候選區(qū)域+手工特征提取+分類器)

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 是一個(gè)構(gòu)建在 TensorFlow 之上的開源框架晴埂,可以輕松構(gòu)建究反、訓(xùn)練和部署對(duì)象檢測(cè)模型。另外儒洛,TensorFlow Object Detection API 還提供了 Model Zoo 方便我們選擇切換預(yù)訓(xùn)練模型精耐。

安裝依賴項(xiàng)

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

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

安裝 API

TensorFlow Object Detection API 官方的安裝步驟較為繁瑣琅锻,筆者寫了一個(gè)腳本直接一鍵安裝卦停。

執(zhí)行 git clone https://github.com/CatchZeng/object-detection-api.git 下載倉(cāng)庫(kù),然后到該倉(cāng)庫(kù)(下文簡(jiǎn)稱 oda 倉(cāng)庫(kù))目錄下恼蓬,執(zhí)行以下命令惊完,如果看到如下輸出,表示安裝成功处硬。

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

OK (skipped=1)

注:如果你不想用 conda小槐,可以在自己的 python 環(huán)境上直接使用 make install 安裝即可,比如在 colab 中使用荷辕。

注:由于 cudaDNNtoolkit 更新可能沒有 TensorFlow 快凿跳。因此,如果你的機(jī)器有 GPU疮方,安裝完成后控嗜,需要將 TensorFlow 降回到 cudaDNNtoolkit 支持的版本這樣才能支持 GPU 訓(xùn)練,以 2.4.1 為例:

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

注:如果安裝失敗骡显,可以參考官方文檔的詳細(xì)步驟安裝疆栏。

工程創(chuàng)建

注:!!! 從這里開始曾掂,請(qǐng)確保在 conda od 的環(huán)境下執(zhí)行。

$ 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 倉(cāng)庫(kù)目錄下壁顶,執(zhí)行以下命令珠洗,創(chuàng)建工程目錄結(jié)構(gòu)。

注:SAVE_DIR 為保存項(xiàng)目的目錄若专,NAME 為項(xiàng)目的名稱险污。

$ make workspace-box SAVE_DIR=workspace NAME=test
└── workspace
    └── test
        ├── Makefile
        ├── annotations:存放標(biāo)注好的數(shù)據(jù)集數(shù)據(jù)(val.record、train.record富岳、label_map.pbtxt)
        ├── convert_quant_lite.py:量化 tflite 模型腳本
        ├── export_tflite_graph_tf2.py:導(dǎo)出 tflite 模型腳本
        ├── exported-models:存放訓(xùn)練完之后導(dǎo)出的模型
        ├── exporter_main_v2.py:導(dǎo)出模型腳本
        ├── images:數(shù)據(jù)集圖片和 xml 標(biāo)注
        │   ├── test:手動(dòng)驗(yàn)證圖片
        │   ├── train:訓(xùn)練集圖片和 xml 標(biāo)注
        │   └── val:驗(yàn)證集圖片和 xml 標(biāo)注
        ├── model_main_tf2.py:訓(xùn)練模型腳本
        ├── models:自定義模型
        ├── pre-trained-models:TensorFlow Model Zoo 提供的預(yù)訓(xùn)練模型
        └── test_images.py:手動(dòng)驗(yàn)證圖片腳本

數(shù)據(jù)集

圖片

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

image

將收集的圖片动壤,放入工程目錄的 images 的三個(gè)子目錄下萝喘。

image

注:本案例只是為了驗(yàn)證如何訓(xùn)練目標(biāo)識(shí)別模型,因此數(shù)據(jù)集采集得比較少琼懊,實(shí)際項(xiàng)目中記得盡量采集多點(diǎn)數(shù)據(jù)集阁簸。

標(biāo)注

收集完圖片后,需要對(duì)訓(xùn)練驗(yàn)證集圖片進(jìn)行標(biāo)注哼丈。標(biāo)注工具启妹,選用較為常用的 LabelImg

根據(jù) installation 的說明安裝好 LabelImg醉旦,然后執(zhí)行 labelImg 選擇 trainval 文件夾進(jìn)行標(biāo)注饶米。

image

標(biāo)注完成后,會(huì)生成圖片對(duì)應(yīng)的 xml 標(biāo)注文件车胡,如下所示:

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

創(chuàng)建 TFRecord

TensorFlow Object Detection API 只支持 TFRecord 格式的數(shù)據(jù)集檬输,因此,需要把標(biāo)注好的數(shù)據(jù)集進(jìn)行轉(zhuǎn)換匈棘。

cd 到工程目錄(cd workspace/test)丧慈,然后執(zhí)行 make gen-tfrecord,將在 annotations 文件夾下生成 label_map.pbtxtTFRecord 格式的數(shù)據(jù)集主卫。

$ make gen-tfrecord
python gen_label_map.py
unsorted:  ['cup', 'teapot', 'humidifier']
sorted:  ['cup', 'humidifier', 'teapot']
item {
  id: 1
  name: 'cup'
}

item {
  id: 2
  name: 'humidifier'
}

item {
  id: 3
  name: 'teapot'
}

python generate_tfrecord.py \
        -x images/train \
        -l annotations/label_map.pbtxt \
        -o annotations/train.record
Successfully created the TFRecord file: annotations/train.record
python 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
# label_map.pbtxt
item {
  id: 1
  name: 'cup'
}

item {
  id: 2
  name: 'humidifier'
}

item {
  id: 3
  name: 'teapot'
}

模型訓(xùn)練

注:!!! 從這里開始逃默,請(qǐng)確保已經(jīng) cd 到工程目錄(cd workspace/test)。

下載預(yù)訓(xùn)練模型

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

如果你選擇的是 SSD MobileNet V2 FPNLite 320x320 可以執(zhí)行如下命令笑旺,自動(dòng)下載并解壓

$ make dl-model

目錄結(jié)構(gòu)如下:

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

配置訓(xùn)練 Pipeline

models 目錄創(chuàng)建對(duì)應(yīng)的模型文件夾,比如: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 如下幾處需要根據(jù)項(xiàng)目修改

model {
  ssd {
    num_classes: 3 # 修改為需要識(shí)別的目標(biāo)個(gè)數(shù),示例項(xiàng)目為 3 種
    ......
}
train_config {
  batch_size: 8 # 這里需要根據(jù)自己的配置乌妙,調(diào)整大小使兔,這里設(shè)置為 8
  ......
  optimizer {
    momentum_optimizer {
      learning_rate {
        cosine_decay_learning_rate {
          learning_rate_base: 0.07999999821186066
          total_steps: 10000 # 修改為想要訓(xùn)練的總步數(shù)
          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" # 修改為預(yù)制模型的路徑
  num_steps: 10000 # 修改為想要訓(xùn)練的總步數(shù)
  startup_delay_steps: 0.0
  replicas_to_aggregate: 8
  max_number_of_boxes: 100
  unpad_groundtruth_tensors: false
  fine_tune_checkpoint_type: "detection" # 這里需要修改為 detection,因?yàn)槲覀兪亲瞿繕?biāo)檢測(cè)
  fine_tune_checkpoint_version: V2
}
train_input_reader {
  label_map_path: "annotations/label_map.pbtxt" # 修改為標(biāo)注的路徑
  tf_record_input_reader {
    input_path: "annotations/train.record" # 修改為訓(xùn)練集的路徑
  }
}
eval_config {
  metrics_set: "coco_detection_metrics"
  use_moving_averages: false
}
eval_input_reader {
  label_map_path: "annotations/label_map.pbtxt" # 修改為標(biāo)注的路徑
  shuffle: false
  num_epochs: 1
  tf_record_input_reader {
    input_path: "annotations/val.record" # 修改為驗(yàn)證集的路徑
  }
}

訓(xùn)練模型

$ make train

注:如遇以下問題

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

執(zhí)行以下命令藤韵,重新安裝下 numpy 即可虐沥。

pip uninstall numpy
pip install numpy

模型導(dǎo)出與轉(zhuǎn)換

  • 普通模型

    $ make export
    
  • TFLite 模型

    $ make export-lite
    
  • 轉(zhuǎn)換 TFLite 模型

    $ make convert-lite
    
  • 轉(zhuǎn)換量化版 TFLite 模型

    $ make convert-quant-lite
    

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

測(cè)試模型

執(zhí)行 make export 導(dǎo)出模型后欲险,將測(cè)試圖片放到 images/test 文件夾下,然后執(zhí)行 python test_images.py 即可輸出標(biāo)記好目標(biāo)的圖片到 images/test_annotated匹涮。

image

小結(jié)

本文通過案例將目標(biāo)檢測(cè)的整個(gè)流程都過了一遍天试,希望能幫助大家快速掌握訓(xùn)練自定義目標(biāo)檢測(cè)器的能力。

案例的代碼和數(shù)據(jù)集都已經(jīng)放在了 https://github.com/CatchZeng/object-detection-api然低,有需要的同學(xué)可以自行獲取喜每。

后面的文章將會(huì)為大家?guī)恚?strong>目標(biāo)檢測(cè)的原理、常用的目標(biāo)檢測(cè)網(wǎng)絡(luò)雳攘,以及目標(biāo)分割带兜。本篇就到這了,咱們下一篇見吨灭。

參考鏈接

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末刚照,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子喧兄,更是在濱河造成了極大的恐慌涩咖,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,941評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件繁莹,死亡現(xiàn)場(chǎng)離奇詭異檩互,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)咨演,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,397評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門闸昨,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人薄风,你說我怎么就攤上這事饵较。” “怎么了遭赂?”我有些...
    開封第一講書人閱讀 165,345評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵循诉,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我撇他,道長(zhǎng)茄猫,這世上最難降的妖魔是什么狈蚤? 我笑而不...
    開封第一講書人閱讀 58,851評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮划纽,結(jié)果婚禮上脆侮,老公的妹妹穿的比我還像新娘。我一直安慰自己勇劣,他們只是感情好靖避,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,868評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著比默,像睡著了一般幻捏。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上命咐,一...
    開封第一講書人閱讀 51,688評(píng)論 1 305
  • 那天粘咖,我揣著相機(jī)與錄音,去河邊找鬼侈百。 笑死,一個(gè)胖子當(dāng)著我的面吹牛翰铡,可吹牛的內(nèi)容都是我干的钝域。 我是一名探鬼主播,決...
    沈念sama閱讀 40,414評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼锭魔,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼例证!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起迷捧,我...
    開封第一講書人閱讀 39,319評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤织咧,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后漠秋,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體笙蒙,經(jīng)...
    沈念sama閱讀 45,775評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,945評(píng)論 3 336
  • 正文 我和宋清朗相戀三年庆锦,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了捅位。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,096評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡搂抒,死狀恐怖艇搀,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情求晶,我是刑警寧澤焰雕,帶...
    沈念sama閱讀 35,789評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站芳杏,受9級(jí)特大地震影響矩屁,放射性物質(zhì)發(fā)生泄漏辟宗。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,437評(píng)論 3 331
  • 文/蒙蒙 一档插、第九天 我趴在偏房一處隱蔽的房頂上張望慢蜓。 院中可真熱鬧,春花似錦郭膛、人聲如沸晨抡。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,993評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽耘柱。三九已至,卻和暖如春棍现,著一層夾襖步出監(jiān)牢的瞬間调煎,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,107評(píng)論 1 271
  • 我被黑心中介騙來泰國(guó)打工己肮, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留士袄,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,308評(píng)論 3 372
  • 正文 我出身青樓谎僻,卻偏偏與公主長(zhǎng)得像娄柳,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子艘绍,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,037評(píng)論 2 355