deeplab v3+訓練自己的資料集
資料集的製作及相關程式碼修改
原始碼連結:deeplab v3+
筆者使用的是類似voc2012的資料集,最終的目的是進行語義分割。要想獲得這樣的資料集可以使用labelme進行標註,也可以使用PS進行處理。筆者使用了PS進行標註,生成了灰度圖。
為了方便,使用的資料集形式與官方資料集一致,如下所示:
其中,在SegmentationClass中Segmentation裡存放train.txt,val.txt等檔案,裡面記錄著用作訓練集驗證集的檔名。JPEGImages中存放著所有的資料,SegmentationClass中存放著JPEGImages中資料對應的標籤。tfrecord之後會存放經過處理的資料。train中會存放生成的訓練檔案,eval會存放生成的評估檔案,vis會存放最終對eval的分割結果。
建立好資料夾後,首先要將原始圖片轉變為tensorflow支援的tfrecord格式。這裡對download_and_convert_voc2012.sh檔案的某些語句進行註釋,因為我們不需要下載與解壓voc資料集。如下所示:
# Helper function to download and unpack VOC 2012 dataset. #download_and_uncompress() { # local BASE_URL=${1} # local FILENAME=${2} # if [ ! -f "${FILENAME}" ]; then # echo "Downloading ${FILENAME} to ${WORK_DIR}" # wget -nd -c "${BASE_URL}/${FILENAME}" # fi # echo "Uncompressing ${FILENAME}" # tar -xf "${FILENAME}" #} # Download the images. #BASE_URL="http://host.robots.ox.ac.uk/pascal/VOC/voc2012/" #FILENAME="VOCtrainval_11-May-2012.tar" #download_and_uncompress "${BASE_URL}" "${FILENAME}"
執行download_and_convert_voc2012.sh檔案製作資料集:
# From the tensorflow/models/research/deeplab/datasets directory.
sh download_and_convert_voc2012.sh
在segmentation_dataset.py中修改如下內容為自己資料的train資料量、val資料量及分類數(num_classes),注意,此處的分類數包括背景:
splits_to_sizes={ 'train': 2358, # 'train_aug': 10582, # 'trainval': 2913, 'val': 590, }, num_classes=6, ignore_label=255,
為了使用預訓練的權重,更改train.py中的True改為False:
flags.DEFINE_boolean('initialize_last_layer', False,
'Initialize the last layer.')
之後按照官方教程進行訓練即可
可能出現問題
1、如果資料集中的圖片大小不一致,在執行eval.py的時候可能出現類似tensorflow.python.framework.errors_impl.InvalidArgumentError: Shape mismatch in tuple component 1. Expected [513,513,3], got [513,616,3] 這樣的錯誤,此時需要根據根據資料集中最大的圖片尺寸修改即可,例如資料集中圖片尺寸最大為624*823,可以設定eval_crop_size為625與825.
2、如果出現類似錯誤:InvalidArgumentError (see above for traceback): assertion failed: [predictions
out of bound] [Condition x < y did not hold element-wise:] [x (mean_iou/confusion_matrix/control_dependency_1:0) = ] [0 3 3…] [y (mean_iou/ToInt64_2:0) = ] [150]
在eval.py修改程式碼如下:
metric_map = {}
# insert by trobr
indices = tf.squeeze(tf.where(tf.less_equal(
labels, dataset.num_classes - 1)), 1)
labels = tf.cast(tf.gather(labels, indices), tf.int32)
predictions = tf.gather(predictions, indices)
# end of insert
metric_map[predictions_tag] = tf.metrics.mean_iou(
predictions, labels, dataset.num_classes, weights=weights)