原文: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)練偶器。
案例效果如下圖所示:
圖像分割
如上圖所示捏题,目標(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) 來做案例骇陈。
將收集的圖片震庭,放入工程目錄的 images
的三個子目錄下。
注:本案例只是為了驗(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
選擇 train
和 val
文件夾進(jìn)行標(biāo)注。
標(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
默垄。
小結(jié)
本文通過案例將圖像分割的整個流程都過了一遍此虑,希望能幫助大家快速掌握訓(xùn)練自定義圖像分割模型的能力。
案例的代碼和數(shù)據(jù)集都已經(jīng)放在了 https://github.com/CatchZeng/object-detection-api口锭,有需要的同學(xué)可以自行獲取朦前。
后面的文章將會為大家?guī)恚?strong>目標(biāo)檢測和目標(biāo)分割的原理以及常用的網(wǎng)絡(luò)。本篇就到這了鹃操,咱們下一篇見韭寸。
參考鏈接
- https://github.com/tensorflow/models/tree/master/research/object_detection
- https://tensorflow-object-detection-api-tutorial.readthedocs.io/en/latest/index.html
- https://github.com/eric-erki/How-To-Train-an-Object-Detection-Classifier-for-Multiple-Objects-Using-TensorFlow-GPU-on-Windows-1
- https://my.oschina.net/u/876354/blog/3055850
- https://stackoverflow.com/questions/53382383/makefile-cant-use-conda-activate
- https://stackoverflow.com/questions/66060487/valueerror-numpy-ndarray-size-changed-may-indicate-binary-incompatibility-exp