天天看點

使用object_detection_api進行訓練和預測使用object_detection_api進行訓練和預測

使用object_detection_api進行訓練和預測

将object_detection_api安裝好以後,我們可以使用其進行transfer learning進而實作對新檢測應用的快速學習,當然也可以使用訓練好的模型進行預測。以下分别講如何使用現有模型進行預測以及在訓練好的模型基礎上使用新資料集學習新的模型。

官網提供了在linux下使用的說明,這裡說明如何在windows下進行使用,筆者在win7下進行了測試并運作成功。

使用現有模型進行預測

運作object_detection模型下的

object_detection_tutorial.ipynb

可以使用ssd_mobilenet_v1模型進行預測。将該notebook中的

MODEL_NAME = 'faster_rcnn_resnet101_coco_2018_01_28'

進行更改即可使用不同的模型進行預測。注意若目前檔案夾下若存放相應模型檔案,該代碼會自動在目前路徑下下載下傳模型檔案。

使用模型從頭開始訓練

Running the Training Job
    A local training job can be run with the following command:

        # From the tensorflow/models/research/ directory
        python object_detection/train.py \
            --logtostderr \
            --pipeline_config_path=${PATH_TO_YOUR_PIPELINE_CONFIG} \
            --train_dir=${PATH_TO_TRAIN_DIR}

    where ${PATH_TO_YOUR_PIPELINE_CONFIG} points to the pipeline config and ${PATH_TO_TRAIN_DIR} points to the directory in which training checkpoints and events will be written to. By default, the training job will run indefinitely until the user kills it.
           

按照官網說明,隻需找到對應模型的pipeline寫好即可。

使用pre-trained模型在新資料集上進行學習

在detection_model_zoo中包含了很多預訓練模型。

為了使用這些模型,我們需要依次準備以下内容:準備資料,設定object detection pipeline。

準備資料

資料準備可以參考原github中的說明。該網站中也提供了各種公開資料集的下載下傳位址。這裡使用的資料是2012 PASCAL VOC data set。準備資料的過程中的輸入為原始資料的解壓檔案夾,輸出為兩個.tfrecord檔案。使用的代碼為

create_pascal_tf_record.py

(其目錄為object_detection/dataset_tools/create_pascal_tf_record.py)

運作指令如下:

python ./dataset_tools/create_pascal_tf_record.py \
--data_dir=./data/VOCdevkit \
--year=VOC2012 \
--set=train \
--label_map_path=./data/pascal_label_map.pbtxt \
--output_path=./data/pascal_train.record
           

對應的檔案結構如下:

--object_detection
    |-- dataset_tools
    |     |-- create_pascal_tf_record.py
    |-- data
    |     |-- VOCdevkit
    |     |-- pascal_label_map.pbtxt
    |
           

代碼運作後會在

object_detection/data

目錄下生成

pascal_train.record

pascal_cal.record

兩個檔案。之後我們使用這兩個檔案作為資料輸入即可。

建立.config設定

在pre-trained模型下載下傳下來後,其内會包含一個

.config

的檔案,我們将其複制一下,改名為

faster_rcnn_resnet101_voc.config

,之後打開該檔案,将

PATH_TO_BE_CONFIGURED

的路徑修改為自己存儲的路徑。如我将檔案以如下結構存放:

--object_detection
    |
    |--demo_VOC2012
    |    |
    |    |--faster_rcnn_resnet101_voc.config 
    |    |
    |    |--model.ckpt
    |    |
    |    |--pascal_train.record
    |    |--pascal_val.record
    |    |--pascal_label_map.pbtxt
           

可将其内代碼改為

fine_tune_checkpoint: "./demo_VOC2012/model.ckpt"

,

input_path: "./demo_VOC2012/pascal_train.record"

,

label_map_path: "./demo_VOC2012/pascal_label_map.pbtxt".

其他代碼保持不變即可。

模型訓練運作以下代碼即可:

python train.py --logtostderr --pipeline_config_path=./demo_VOC2012/faster_rcnn_resnet101_voc.config --train_dir=./demo_VOC2012/train
           

可能出現的問題

由于object_detection_API官方教程在linux下運作,加之其仍在測試階段,是以可能會有一些bug和錯誤出現,這裡列舉一些我遇到的問題和解決方法。

  1. failed: tried to convert ‘t’ to a tensor. Argument must be a dense tensor range (0, 3) got shape [3], but wanted []

    這個問題出在learning_schedule.py檔案。需找到安裝api時的目錄下的learning_schedule.py,将

    rate_index = tf.reduce_max(tf.where(tf.greater_equal(global_step, boundaries),
                                    range(num_boundaries),
                                    [0] * num_boundaries))
    rate_index = tf.reduce_max(tf.where(tf.greater_equal(global_step, boundaries),
                                    list(range(num_boundaries)),
                                    [0] * num_boundaries))
               
    方法來源:github_issue
  2. DataLossError: Unable to open table file Input/output Error

    這個問題是model restore的問題,由于新的模型存儲從.ckpt變為存儲為三個.ckpt檔案,是以将fine_tune_checkpoints=設定為三個檔案所在檔案夾/model.ckpt即可。

  3. No module named ‘pycocotools’

    這個應該是由于cocoAPI沒有安裝的問題,但是官網僅僅提供了linux下安裝的方法,win7下的安裝目前我仍未成功。

    參考github-issue和github-issue,我從philferriere-github中下載下傳了

    cocoapi-master

    ,解壓後分别運作
    python setup.py build_ext --inplace
    python setup.py build_ext install
               
    (即makefile中的指令). 執行後沒報錯,且eval.py運作不再報上述問題了。

使用tensorflow object detection api訓練自己的資料

資料存放結構

為了可以在api中使用自己生成的資料,與PASCAL VOC處理方法相似,我們需将資料檔案夾轉為tfrecord。相似地,我們采用相同的資料存放結構,我們将自己的資料以如下檔案結構存放:

--data
  |--label_map.pbtxt
  |--VOC2007
  |    |--Annotations
  |    |--ImageSets
  |    |    |--Main
  |    |    |    |--train.txt
  |    |--JPEGImages
--create_xx_tf_record.py
           

其中

annotations

檔案夾中存放标注檔案(以xml格式檔案存放),

JPEGImages

檔案夾中存放原圖(以jpg格式存放),而

label_map.pbtxt

檔案需自己來寫,其内以字典形式存放不同的label類别(分類名稱對應的整型分類),如:

item {
  id: 1
  name: cat
}
item {
  id: 2
  name: dog
}
           

這些檔案都可以參考PASCAL VOC的示例來寫。

資料處理代碼

create_pascal_tf_record.py

(在object_detection/dataset_tool目錄下)複制到與

data

檔案夾同目錄下,這裡我重命名為

create_xx_tf_record.py

。我們需要對其相關參數進行修改使其與自己的資料相比對。如下:

data_dir 設為 ./data
label_map_path 設為 ./data/label_map.pbtxt
output_path 設為 ./data/xx_train.tfrecord

# 注釋下列幾個不用的語句
  # difficult_obj.append(int(difficult))
  # truncated.append(int(obj['truncated']))
  # poses.append(obj['pose'].encode('utf8'))
  # 'image/object/difficult': dataset_util.int64_list_feature(difficult_obj),
  # 'image/object/truncated': dataset_util.int64_list_feature(truncated),
  # 'image/object/view': dataset_util.bytes_list_feature(poses),

# 若xml中未設定圖像的width和height,則将
  width = int(data['size']['width'])
  height = int(data['size']['height'])
  改為 width, height = image.size

# 修改main函數中image path
    examples_path = os.path.join(data_dir, year, 'ImageSets', 'Main',
                             'train' + '.txt')
# 調試時一定要確定dict_to_tf_example()函數中full_path和主函數中的data都讀取正确。
# 生成各檔案時需保證.jpg和.xml一一對應,且和.pbtxt中的一緻。
           

将以上改動設定好以後,運作create.py則可在output_path中生成tfrecord檔案。

xml檔案修改

create_xx_tf_record.py

img_path

變量的設定中用到了

xml

中的

folder

标簽值(data[‘folder’]),是以需将

xml

中folder标簽值改為image存放路徑:

VOC2007

。該問題使用以下代碼運作即可。

from xml.etree.ElementTree import parse, Element
import os

filepath = './xml'
xml_files = os.listdir(filepath)
for xml_file in xml_files:
    print("now {} is being processed".format(xml_file))
    xml_path = os.path.join(filepath, xml_file)
    doc = parse(xml_path)
    root = doc.getroot()

    # # Remove a few elements
    # root.remove(root.find('sri'))
    # root.remove(root.find('cr'))
    # # Insert a new element after <nm>...</nm>
    # root.getchildren().index(root.find('nm'))
    #
    # e = Element('spam')
    # e.text = 'This is a test'
    # root.insert(2, e)
    folder = root.find('folder')  # folder是<>中的值
    folder.text = 'VOC2007'  # text是<><>之間的值

    # Write back to a file
    # doc.write(xml_file, xml_declaration=True)
    doc.write(xml_file)
           

參考:python3-cookbook解析和修改xml

一些error

  1. 轉存後的xml檔案encoding=”US-ASCII”出錯:

    這時需要注意doc.write()中encoding, xnl_declaration參數的設定

  2. float: division by zero

    width不能設定為0,按照上述方法設定

  3. 圖檔讀入時出錯,if image.format != ‘JPEG’:

    圖檔字尾是jpg不一定是jpg。需要使用二進制檢視圖檔确定檔案頭(如wxMEdit)

修改.config配置檔案

同樣的,需在預訓練模型的config檔案基礎上進行修改。主要修改以下參數:

  • num_classes: 分類數目。視資料分類數目而定
  • fine_tune_checkpoint:修改成github上下載下傳的faster_rcnn的ckpt檔案會導緻無法訓練的情況
  • step: 控制疊代數

訓練代碼檔案存放結構

參考上篇總結,進行相似存放即可。訓練時運作

python train.py --logtostderr --pipeline_config_path=./demo_XX/faster_rcnn_resnet101_xx.config --train_dir=./demo_XX/train    
           

eval時運作

python eval.py --logtostderr --pipeline_config_path=./demo_VOC2012/faster_rcnn_resnet101_xx.config --checkpoint_dir=./demo_xx/train --eval_dir=./demo_xx/eval
           

即可。

使用訓練得到的ckpt進行預測

預測使用的代碼是從object_detection_tutorial複制改寫得到的,改名為demo_faster_rcnn_resnet101_xx.py。需要修改其中以下内容:

PATH_TO_CKPT = "./demo_XX/output/frozen_inference_graph.pb"  # .pb檔案存儲訓練好的模型
PATH_TO_LABELS = './demo_XX/xx_label_map.pbtxt'  
num_classes = 4
PATH_TO_TEST_IMAGE_DIR = 'test_images'
TEST_IMAGE_PATHS = [ os.path.join(PATH_TO_TEST_IMAGES_DIR, '00000{}.jpg'.format(i)) for i in range(1, 10) ]
           

其檔案結構如下:

object detection
  |
  |--test_images
  |--demo_XX
  |     |
  |     |--train
  |     |--output
  |     |    |
  |     |    |--frozen_inference_graph.pb
  |     |--xx_label_map.pbtxt
  |--export_inference_graph.py
  |--demo_faster_rcnn_resnet101_xx.py
           

執行時需先将訓練好的模型轉為.pb格式檔案(過程後述),然後在test_images檔案夾中存放測試圖像,同時測試資料的名稱要以清單形式存放在TEST_IMAGE_PATHS中。準備妥當以後,運作

python demo_faster_rcnn_resnet101_xx.py
           

即可進行預測。

.ckpt轉存為.pb檔案

同樣在

/object detection

檔案夾中,

export_inference_graph.py

可以完成這個功能。運作該腳本隻需将

原始ckpt.meta所在檔案夾目錄

,

輸出目錄

, 以及

pipeline目錄

設定好即可。如執行以下指令:

python export_inference_graph.py --input_type image_tensor --pipeline_config_path ./demo_XX/faster_rcnn_resnet101_xx.config --trained_checkpoint_prefix ./demo_XX/train/model.ckpt-83082 --output_directory ./demo_XX/output
           

整個過程總結與檔案存放結構

  • 生成資料
    |--create_xx_tf_record.py
    |
    |--data
    |    |--VOC2007
    |    |    |--Annotations
    |    |    |    |--xml檔案
    |    |    |--ImageSets
    |    |    |    |--Main
    |    |    |    |   |--txt檔案
    |    |    |--JPEGImages
    |    |    |    |--jpg檔案
               
  • 完成訓練
    object_detection
        |
        |--demo_xx (存放某個應用/資料訓練的結果)
        |    |
        |    |--train(訓練model目錄)
        |    |--faster_rcnn_resnet101_xx.config (預訓練模型config,設定模型超參數)
        |    |--model.ckpt(三個)
        |    |--train.record
        |    |--val.record
        |    |--.pbtxt(資料label标注檔案)
               
  • 完成測試(或完成eval)
    object detection
        |
        |--test_images (存放測試資料集圖像)
        |--demo_XX (存放某個應用/資料訓練的結果)
        |     |
        |     |--train(訓練好的model目錄)
        |     |--output
        |     |    |
        |     |    |--frozen_inference_graph.pb(訓練好轉存為.pb檔案)
        |     |--xx_label_map.pbtxt
        |--export_inference_graph.py
        |--demo_faster_rcnn_resnet101_xx.py
               

整個檔案結構(注意生成資料可以不依賴object detection庫,可以在單獨的檔案夾下執行)

object detection
    |
    |--dataset tools
    |    |--create_xx_tf_record.py
    |    |
    |    |--data
    |    |    |--VOC2007
    |    |    |    |--Annotations
    |    |    |    |    |--xml檔案
    |    |    |    |--ImageSets
    |    |    |    |    |--Main
    |    |    |    |    |   |--txt檔案
    |    |    |    |--JPEGImages
    |    |    |    |    |--jpg檔案
    |
    |--demo_xx (存放某個應用/資料訓練的結果)
    |    |
    |    |--train(訓練model目錄)
    |    |--output
    |    |    |--frozen_inference_graph.pb(訓練好轉存為.pb檔案)

    |    |--faster_rcnn_resnet101_xx.config (預訓練模型config,設定模型超參數)
    |    |--model.ckpt(三個)
    |    |--train.record
    |    |--val.record
    |    |--.pbtxt(資料label标注檔案)

    |--test_images (存放測試資料集圖像)
    |--export_inference_graph.py(用于将.ckpt檔案轉化為.pb)
    |--demo_faster_rcnn_resnet101_xx.py(用于預測test)
           

繼續閱讀