易 AI - 使用 TensorFlow Object Detection API Mask R-CNN 訓(xùn)練自定義圖像分割模型

原文:https://makeoptim.com/en/deep-learning/yiai-image-segmentation

前言

上一篇介紹了目標(biāo)檢測(Object Detection)消恍,本文將介紹圖像分割(Image Segmentation)的概念,并通過案例講解如何使用 TensorFlow Object Detection API 來訓(xùn)練自定義的圖像分割模型薯定,包括:數(shù)據(jù)集采集和制作贴膘、TensorFlow Object Detection API 安裝以及模型的訓(xùn)練偶器。

案例效果如下圖所示:

image

圖像分割

image

如上圖所示捏题,目標(biāo)檢測識別圖像中存在的內(nèi)容和檢測其位置髓需,而圖像分割分為以下三種類型:

  • 語義分割(semantic segmentation):對圖像中的每個像素打上類別標(biāo)簽凿可,如上圖,把圖像分為人(紅色)授账、樹木(深綠)枯跑、草地(淺綠)、天空(藍(lán)色)標(biāo)簽白热。
  • 實(shí)例分割(instance segmentation)目標(biāo)檢測和語義分割的結(jié)合敛助,在圖像中將目標(biāo)檢測出來(目標(biāo)檢測),然后對每個像素打上標(biāo)簽(語義分割)屋确。如上圖纳击,以人為目標(biāo),語義分割不區(qū)分屬于相同類別的不同實(shí)例(所有人都標(biāo)為紅色)攻臀,實(shí)例分割區(qū)分同類的不同實(shí)例(使用不同顏色區(qū)分不同的人)焕数。
  • 全景分割(panoptic segmentation)語義分割和實(shí)例分割的結(jié)合,即要對所有目標(biāo)都檢測出來刨啸,又要區(qū)分出同個類別中的不同實(shí)例堡赔。如上圖,實(shí)例分割只對圖像中的目標(biāo)(如上圖中的人)進(jìn)行檢測和按像素分割设联,區(qū)分不同實(shí)例(使用不同顏色)善已,而全景分割是對圖中的所有物體包括背景都要進(jìn)行檢測和分割,區(qū)分不同實(shí)例(使用不同顏色)离例。

本文要使用的 Mask R-CNN 正是一個實(shí)例分割模型换团。

TensorFlow Object Detection API

TensorFlow Object Detection API 的安裝與目標(biāo)檢測一致,參考上一篇 即可宫蛆,這里不再贅述艘包。

工程創(chuà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 倉庫目錄下想虎,執(zhí)行以下命令衰絮,創(chuàng)建工程目錄結(jié)構(gòu)。

注:SAVE_DIR 為保存項(xiàng)目的目錄磷醋,NAME 為項(xiàng)目的名稱猫牡。

$ make workspace-mask SAVE_DIR=workspace NAME=test-mask
└── workspace
    └── test-mask
        ├── COCO_Image_Viewer.ipynb:用于驗(yàn)證是否成功轉(zhuǎn)換到 COCO format
        ├── Makefile
        ├── annotations:存放標(biāo)注好的數(shù)據(jù)集數(shù)據(jù)(val.record、train.record邓线、label_map.pbtxt)
        ├── create_coco_tf_record.py:將 COCO format 文件轉(zhuǎn)換為 TFRecord
        ├── exported-models:存放訓(xùn)練完之后導(dǎo)出的模型
        ├── exporter_main_v2.py:導(dǎo)出模型腳本
        ├── images:數(shù)據(jù)集圖片和 json 標(biāo)注
        │   ├── test:手動驗(yàn)證圖片
        │   ├── train:訓(xùn)練集圖片和 json 標(biāo)注
        │   └── val:驗(yàn)證集圖片和 json 標(biāo)注
        ├── labelme2coco.py:將 labelme json 文件轉(zhuǎn)換為 COCO format
        ├── model_main_tf2.py:訓(xùn)練模型腳本
        ├── models:自定義模型
        ├── pre-trained-models:[TensorFlow Model Zoo](https://github.com/tensorflow/models/blob/master/research/object_detection/g3doc/tf2_detection_zoo.md) 提供的預(yù)訓(xùn)練模型
        └── test_images.py:手動驗(yàn)證圖片腳本

數(shù)據(jù)集

圖片

這里還是使用茶杯(cup)淌友、茶壺(teapot)、加濕器(humidifier) 來做案例骇陈。

image

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

image

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

標(biāo)注

收集完圖片后婿崭,需要對訓(xùn)練驗(yàn)證集圖片進(jìn)行標(biāo)注拨拓。標(biāo)注工具,選用較為常用的 labelme氓栈。

根據(jù) installation 的說明安裝好 labelme渣磷,然后執(zhí)行 labelme 選擇 trainval 文件夾進(jìn)行標(biāo)注。

image

標(biāo)注完成后授瘦,會生成圖片對應(yīng)的 json 標(biāo)注文件醋界,如下所示:

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

生成 TFRecord 和 label_map

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

cd 到工程目錄(cd workspace/test-mask),然后執(zhí)行 make gen-tfrecord徒欣,將在 annotations 文件夾下生成 TFRecord 格式的數(shù)據(jù)集和 label_map.pbtxt逐样。

$ make gen-tfrecord
python labelme2coco.py images/train --output images/train.json
save coco json
images/train.json
python labelme2coco.py images/val --output images/val.json
save coco json
images/val.json
python create_coco_tf_record.py --logtostderr \
        --train_image_dir=images/train \
        --val_image_dir=images/val \
        --train_annotations_file=images/train.json \
        --val_annotations_file=images/val.json \
        --include_masks=True \
        --output_dir=./annotations
......
python gen_label_map.py
item {
  id: 1
  name: 'cup'
}

item {
  id: 2
  name: 'humidifier'
}

item {
  id: 3
  name: 'teapot'
}
annotations
├── label_map.pbtxt
├── train.record
└── val.record

注:如果想驗(yàn)證是否將 labelme json 成功轉(zhuǎn)換到 COCO format,可以運(yùn)行 COCO_Image_Viewer.ipynb 查看結(jié)果帚称。

模型訓(xùn)練

注:!!! 從這里開始官研,請確保已經(jīng) cd 到工程目錄(cd workspace/test-mask)。

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

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

這里默認(rèn)選擇的是 mask_rcnn_inception_resnet_v2_1024x1024_coco17_gpu-8 可以執(zhí)行如下命令,自動下載并解壓

$ make dl-model

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

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

配置訓(xùn)練 Pipeline

models 目錄創(chuàng)建對應(yīng)的模型文件夾担神,比如:mask_rcnn_inception_resnet_v2_1024x1024_coco17_gpu-8楼吃,并拷貝 pre-trained-models/mask_rcnn_inception_resnet_v2_1024x1024_coco17_gpu-8/pipeline.config

└── test-mask
    ├── models
    │   └── mask_rcnn_inception_resnet_v2_1024x1024_coco17_gpu-8
    │       └── pipeline.config
    └── pre-trained-models

其中,pipeline.config 如下幾處需要根據(jù)項(xiàng)目修改

model {
  faster_rcnn {
    num_classes: 3 # 修改為需要識別的目標(biāo)個數(shù)孩锡,示例項(xiàng)目為 3 種
    ......
}
train_config {
  batch_size: 8 # 這里需要根據(jù)自己的配置酷宵,調(diào)整大小,這里設(shè)置為 8
  num_steps: 10000 # 修改為想要訓(xùn)練的總步數(shù)
  optimizer {
    momentum_optimizer {
      learning_rate {
        cosine_decay_learning_rate {
          learning_rate_base: 0.008
          total_steps: 10000 # 修改為想要訓(xùn)練的總步數(shù)
          warmup_learning_rate: 0.0
          warmup_steps: 50
        }
      }
      momentum_optimizer_value: 0.8999999761581421
    }
    use_moving_average: false
  }
  gradient_clipping_by_norm: 10.0
  fine_tune_checkpoint_version: V2 # 增加此項(xiàng)躬窜,并指定為 V2 版本
  fine_tune_checkpoint: "pre-trained-models/mask_rcnn_inception_resnet_v2_1024x1024_coco17_gpu-8/checkpoint/ckpt-0" # 修改為預(yù)制模型的路徑
  fine_tune_checkpoint_type: "detection" # 增加此項(xiàng)并設(shè)置為 detection浇垦,因?yàn)槲覀兪亲瞿繕?biāo)檢測
  data_augmentation_options {
    random_horizontal_flip {
    }
  }
}
train_input_reader {
  label_map_path: "annotations/label_map.pbtxt" # 增加此項(xiàng)
  tf_record_input_reader {
    input_path: "annotations/train.record" # 修改為訓(xùn)練集的路徑
  }
  load_instance_masks: true
  mask_type: PNG_MASKS
}
eval_config {
  metrics_set: "coco_detection_metrics"
  metrics_set: "coco_mask_metrics"
  eval_instance_masks: true
  use_moving_averages: false
  batch_size: 1
  include_metrics_per_category: true
}
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)證集的路徑
  }
  load_instance_masks: true
  mask_type: PNG_MASKS
}

訓(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)出

$ make export

測試模型

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

image

小結(jié)

本文通過案例將圖像分割的整個流程都過了一遍此虑,希望能幫助大家快速掌握訓(xùn)練自定義圖像分割模型的能力。

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

后面的文章將會為大家?guī)恚?strong>目標(biāo)檢測和目標(biāo)分割的原理以及常用的網(wǎng)絡(luò)。本篇就到這了鹃操,咱們下一篇見韭寸。

參考鏈接

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市荆隘,隨后出現(xiàn)的幾起案子棒仍,更是在濱河造成了極大的恐慌,老刑警劉巖臭胜,帶你破解...
    沈念sama閱讀 222,590評論 6 517
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件莫其,死亡現(xiàn)場離奇詭異,居然都是意外死亡耸三,警方通過查閱死者的電腦和手機(jī)乱陡,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,157評論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來仪壮,“玉大人憨颠,你說我怎么就攤上這事』” “怎么了爽彤?”我有些...
    開封第一講書人閱讀 169,301評論 0 362
  • 文/不壞的土叔 我叫張陵,是天一觀的道長缚陷。 經(jīng)常有香客問我适篙,道長,這世上最難降的妖魔是什么箫爷? 我笑而不...
    開封第一講書人閱讀 60,078評論 1 300
  • 正文 為了忘掉前任嚷节,我火速辦了婚禮聂儒,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘硫痰。我一直安慰自己衩婚,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,082評論 6 398
  • 文/花漫 我一把揭開白布效斑。 她就那樣靜靜地躺著非春,像睡著了一般。 火紅的嫁衣襯著肌膚如雪缓屠。 梳的紋絲不亂的頭發(fā)上奇昙,一...
    開封第一講書人閱讀 52,682評論 1 312
  • 那天,我揣著相機(jī)與錄音藏研,去河邊找鬼敬矩。 笑死,一個胖子當(dāng)著我的面吹牛蠢挡,可吹牛的內(nèi)容都是我干的弧岳。 我是一名探鬼主播,決...
    沈念sama閱讀 41,155評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼业踏,長吁一口氣:“原來是場噩夢啊……” “哼禽炬!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起勤家,我...
    開封第一講書人閱讀 40,098評論 0 277
  • 序言:老撾萬榮一對情侶失蹤腹尖,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后伐脖,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體热幔,經(jīng)...
    沈念sama閱讀 46,638評論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,701評論 3 342
  • 正文 我和宋清朗相戀三年讼庇,在試婚紗的時候發(fā)現(xiàn)自己被綠了绎巨。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,852評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡蠕啄,死狀恐怖场勤,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情歼跟,我是刑警寧澤和媳,帶...
    沈念sama閱讀 36,520評論 5 351
  • 正文 年R本政府宣布,位于F島的核電站哈街,受9級特大地震影響留瞳,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜叹卷,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,181評論 3 335
  • 文/蒙蒙 一撼港、第九天 我趴在偏房一處隱蔽的房頂上張望坪它。 院中可真熱鬧骤竹,春花似錦帝牡、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,674評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至懒震,卻和暖如春罩息,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背个扰。 一陣腳步聲響...
    開封第一講書人閱讀 33,788評論 1 274
  • 我被黑心中介騙來泰國打工瓷炮, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人递宅。 一個月前我還...
    沈念sama閱讀 49,279評論 3 379
  • 正文 我出身青樓娘香,卻偏偏與公主長得像,于是被迫代替她去往敵國和親办龄。 傳聞我的和親對象是個殘疾皇子烘绽,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,851評論 2 361

推薦閱讀更多精彩內(nèi)容