新手也會用AI | 訓練屬於自己的模型 | 自訂物件識別 | 人工智能 | TensorFlow

介紹

在上一篇入門AI物件識別介紹當中,我們嘗試透過使用Tensorflow提供的模型來進行物件檢測與識別。
我們也會發現,其模型並不能準確分辨每種物件。可否有一套自己的AI模型識別自己想檢測的物件呢?
這次,我們將會訓練自己的一套模型,專門檢測你想識別的東西!訓練自己的模型!



環境配置

下載圖片標籤工具

首先,在Github下載並安裝圖片標籤工具 https://github.com/tzutalin/labelImg
根據裝置安裝PyQt5,因為標籤工具需要Python3 + PyQt5的配置,詳情參考上面網頁,下面也會提供代碼

1
pip3 install PyQt5

它可以讓我們標籤不同的物件,來告訴電腦這些圖片中的物件是什麼,再讓電腦慢慢學習
最後,讓電腦在一張它沒見過的照片當中識別出物件,再反饋告訴我們,這就機器學習中的監督學習(supervised learning)

安裝pandas

Pandas 是python 的一個數據分析庫,為用戶提供高效能、簡易使用的資料格式,讓使用者可以快速操作及分析資料

1
pip3 install pandas

準備工作環境

如果你有一直跟著上一集的教程,那麼你將會有著與我類似的資料夾配置
此時你需要在新建一個名為workspace的資料夾,目錄內再新建training_demo資料夾,工作環境如下:

1
2
3
4
5
6
7
8
TensorFlow
├─ models
│ ├─ official
│ ├─ research
│ ├─ samples
│ └─ tutorials
└─ workspace
└─ training_demo

在training_demo資料夾內,我們會準備自訂的圖片和文件,作為訓練模型之用,因此我們需要準備目錄內的工作環境:

1
2
3
4
5
6
7
training_demo
├─ annotations
├─ images
│ ├─ test
│ └─ train
├─ pre-trained-model
└─ training
關於以上各項資料夾用途的解釋:
annotations: 儲存 .csv 文件以及Tensorflow的 .record 文件,包含著我們所提供的圖片的注釋
images: 包含著我們訓練模型所使用的圖片,和相對應的 .xml 文件(labelImg標籤後產生的文件)
test/train: 我們會把80%的圖片放進train文件裡訓練模型,其餘20%的圖片則會分類為test,目的是測試以及提高模型準確度
pre-trained-model: 包含著我們使用訓練新模型所使用的原模型
training: 儲存著我們訓練模型所產生的的文件,配置文件 .config 以及 .pbtxt 標籤地圖文件

下載圖片

為每種(1種也可)物品準備25張圖片,把其中20張(80%)放進train文件夾,其餘5張(20%)放進test文件夾

使用labelImg工具標籤圖片

運行labelImg工具並打開目錄

運行先前安裝好的LabelImg圖片標籤軟件,分別在程式內打開(Open Dir) train和test目錄,並且對圖片進行標籤


對圖片進行標籤

接著就可以標籤圖片中的物件了,建立方框並打上label名稱,再手動保存 .xml檔就可以了,每張圖片都需重複以上步驟
這裡推薦大家使用快捷鍵: w (建立方框) , Crtl+S / Command+S (保存) , d (下一張圖片)
標籤完所有圖片之後,我們就會發現train和test目錄下的每張圖片都有它所對應的.xml文檔


創建Label map標籤地圖

Tensorflow需要標籤地圖(label map)作為標記物件名稱,這裡創造一個label_map.pbtxt文件
內容按自己定義的物件修改,示範代碼如下,然後將文件放入 training_demo\annotations 目錄下

1
2
3
4
5
6
7
8
9
item {
id: 1
name: 'Garen'
}

item {
id: 2
name: 'Darius'
}

創建TensorFlow Records

這裡有2個步驟,分別是:
1)將獨立的 .xml檔案轉換為 .csv 用作數據集用途
2)把 .csv文件轉換為TFRecord格式的 .record文件
要完成上列2步,需要寫2個獨立的代碼文件
為方便管理資料夾,我們新建一個名為scripts的文件夾,裡面包括preprocessing資料夾,然後開始寫代碼吧!

.xml to .csv 文件轉換

簡單寫一個python文件,名為 xml_to_csv.py ,下面會提供(可直接複製),然後把它放在scripts\preprocessing目錄下
它的功能是分別把images\train 及 images\test 內的.xml文件都轉換為各自的 .csv文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
import os
import glob
import pandas as pd
import argparse
import xml.etree.ElementTree as ET


def xml_to_csv(path):
"""Iterates through all .xml files (generated by labelImg) in a given directory and combines them in a single Pandas datagrame.

Parameters:
----------
path : {str}
The path containing the .xml files
Returns
-------
Pandas DataFrame
The produced dataframe
"""

xml_list = []
for xml_file in glob.glob(path + '/*.xml'):
tree = ET.parse(xml_file)
root = tree.getroot()
for member in root.findall('object'):
value = (root.find('filename').text,
int(root.find('size')[0].text),
int(root.find('size')[1].text),
member[0].text,
int(member[4][0].text),
int(member[4][1].text),
int(member[4][2].text),
int(member[4][3].text)
)
xml_list.append(value)
column_name = ['filename', 'width', 'height',
'class', 'xmin', 'ymin', 'xmax', 'ymax']
xml_df = pd.DataFrame(xml_list, columns=column_name)
return xml_df


def main():
# Initiate argument parser
parser = argparse.ArgumentParser(
description="Sample TensorFlow XML-to-CSV converter")
parser.add_argument("-i",
"--inputDir",
help="Path to the folder where the input .xml files are stored",
type=str)
parser.add_argument("-o",
"--outputFile",
help="Name of output .csv file (including path)", type=str)
args = parser.parse_args()

if(args.inputDir is None):
args.inputDir = os.getcwd()
if(args.outputFile is None):
args.outputFile = args.inputDir + "/labels.csv"

assert(os.path.isdir(args.inputDir))

xml_df = xml_to_csv(args.inputDir)
xml_df.to_csv(
args.outputFile, index=None)
print('Successfully converted xml to csv.')


if __name__ == '__main__':
main()

下一步,開啟終端機,cd到TensorFlow/scripts/preprocessing目錄下,Windows用戶根據以下2行代碼運行xml_to_csv.py文件
[PATH_TO_IMAGES_FOLDER]是images資料夾的根目錄,[PATH_TO_ANNOTATIONS_FOLDER]則是annotations資料夾的根目錄

1
2
3
4
5
6
7
python3 xml_to_csv.py -i [PATH_TO_IMAGES_FOLDER]\train -o [PATH_TO_ANNOTATIONS_FOLDER]\train_labels.csv

python3 xml_to_csv.py -i [PATH_TO_IMAGES_FOLDER]\test -o [PATH_TO_ANNOTATIONS_FOLDER]\test_labels.csv

# 舉個例子 For example:
python3 xml_to_csv.py -i C:\Users\sglvladi\Documents\TensorFlow\workspace\training_demo\images\train -o C:\Users\sglvladi\Documents\TensorFlow\workspace\training_demo\annotations\train_labels.csv
python3 xml_to_csv.py -i C:\Users\sglvladi\Documents\TensorFlow\workspace\training_demo\images\test -o C:\Users\sglvladi\Documents\TensorFlow\workspace\training_demo\annotations\test_labels.csv

MacOS以及Linux用戶的代碼類似,只是 “/“ 和 “\“ 的符號不同,這邊也給大家提供我的代碼作參考

1
2
3
4
5
6
7
#Linux
python3 xml_to_csv.py -i /home/icthk/Desktop/Tensorflow/workspace/training_demo/images/train -o /home/icthk/Desktop/hi/workspace/training_demo/annotations/train_labels.csv
python3 xml_to_csv.py -i /home/icthk/Desktop/Tensorflow/workspace/training_demo/images/test -o /home/icthk/Desktop/hi/workspace/training_demo/annotations/test_labels.csv

#Mac
python3 xml_to_csv.py -i /Users/icthk/Desktop/Tensorflow/workspace/training_demo/images/train -o /Users/icthk/Desktop/Tensorflow/workspace/training_demo/annotations/train_labels.csv
python3 xml_to_csv.py -i /Users/icthk/Desktop/Tensorflow/workspace/training_demo/images/test -o /Users/icthk/Desktop/Tensorflow/workspace/training_demo/annotations/test_labels.csv

當上步驟完成後,2個新文件分別是 test_labels.csv 和 train_labels.csv 將會出現在 training_demo\annotations 資料夾內

.csv to .record 文件轉換

現在我們有了 .csv 格式的注釋文件,接下來就要把他們轉換為TFRecords
在 scripts\preprocessing 建立另一個新的文件,命名為generate_tfrecord.py ,代碼如下
注意!這裡的31-34行代碼需要根據用戶需要作調整,請仔細查看代碼中的注釋!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
from __future__ import division
from __future__ import print_function
from __future__ import absolute_import

import os
import io
import pandas as pd
import tensorflow as tf
import sys
sys.path.append("../../models/research")

from PIL import Image
from object_detection.utils import dataset_util
from collections import namedtuple, OrderedDict

flags = tf.app.flags
flags.DEFINE_string('csv_input', '', 'Path to the CSV input')
flags.DEFINE_string('output_path', '', 'Path to output TFRecord')
flags.DEFINE_string('label', '', 'Name of class label')
# if your image has more labels input them as ,若一張圖片內注釋了多個標籤,請使用以下代碼
# flags.DEFINE_string('label0', '', 'Name of class[0] label')
# flags.DEFINE_string('label1', '', 'Name of class[1] label')
# and so on.
flags.DEFINE_string('img_path', '', 'Path to images')
FLAGS = flags.FLAGS


# TO-DO replace this with label map
# for multiple labels add more else if statements
def class_text_to_int(row_label):
if row_label == 'Garen': # '標籤物件1':
return 1
elif row_label == 'Darius': # '標籤物件2': ***若只有一個標籤物件則刪除33-34行
return 2
# comment upper if statement and uncomment these statements for multiple labelling
# if row_label == FLAGS.label0:
# return 1
# elif row_label == FLAGS.label1:
# return 0
else:
return 0


def split(df, group):
data = namedtuple('data', ['filename', 'object'])
gb = df.groupby(group)
return [data(filename, gb.get_group(x)) for filename, x in zip(gb.groups.keys(), gb.groups)]


def create_tf_example(group, path):
with tf.gfile.GFile(os.path.join(path, '{}'.format(group.filename)), 'rb') as fid:
encoded_jpg = fid.read()
encoded_jpg_io = io.BytesIO(encoded_jpg)
image = Image.open(encoded_jpg_io)
width, height = image.size

filename = group.filename.encode('utf8')
image_format = b'jpg'
# check if the image format is matching with your images.
xmins = []
xmaxs = []
ymins = []
ymaxs = []
classes_text = []
classes = []

for index, row in group.object.iterrows():
xmins.append(row['xmin'] / width)
xmaxs.append(row['xmax'] / width)
ymins.append(row['ymin'] / height)
ymaxs.append(row['ymax'] / height)
classes_text.append(row['class'].encode('utf8'))
classes.append(class_text_to_int(row['class']))

tf_example = tf.train.Example(features=tf.train.Features(feature={
'image/height': dataset_util.int64_feature(height),
'image/width': dataset_util.int64_feature(width),
'image/filename': dataset_util.bytes_feature(filename),
'image/source_id': dataset_util.bytes_feature(filename),
'image/encoded': dataset_util.bytes_feature(encoded_jpg),
'image/format': dataset_util.bytes_feature(image_format),
'image/object/bbox/xmin': dataset_util.float_list_feature(xmins),
'image/object/bbox/xmax': dataset_util.float_list_feature(xmaxs),
'image/object/bbox/ymin': dataset_util.float_list_feature(ymins),
'image/object/bbox/ymax': dataset_util.float_list_feature(ymaxs),
'image/object/class/text': dataset_util.bytes_list_feature(classes_text),
'image/object/class/label': dataset_util.int64_list_feature(classes),
}))
return tf_example


def main(_):
writer = tf.python_io.TFRecordWriter(FLAGS.output_path)
path = os.path.join(os.getcwd(), FLAGS.img_path)
examples = pd.read_csv(FLAGS.csv_input)
grouped = split(examples, 'filename')
for group in grouped:
tf_example = create_tf_example(group, path)
writer.write(tf_example.SerializeToString())

writer.close()
output_path = os.path.join(os.getcwd(), FLAGS.output_path)
print('Successfully created the TFRecords: {}'.format(output_path))


if __name__ == '__main__':
tf.app.run()

然後做法與上個文件類似,我們cd到 TensorFlow\scripts\preprocessing 目錄下運行以下代碼:
[PATH_TO_ANNOTATIONS_FOLDER]是annotations資料夾的根目錄,[PATH_TO_IMAGES_FOLDER]是images資料夾的根目錄
運行代碼稍微會有點長,建議開啟記事本編輯作參考,Windows用戶代碼參考:

1
2
3
4
5
6
7
python3 generate_tfrecord.py  --csv_input=<PATH_TO_ANNOTATIONS_FOLDER>\train_labels.csv --img_path=<PATH_TO_IMAGES_FOLDER>\train  --output_path=<PATH_TO_ANNOTATIONS_FOLDER>\train.record

python3 generate_tfrecord.py --csv_input=<PATH_TO_ANNOTATIONS_FOLDER>\test_labels.csv --img_path=<PATH_TO_IMAGES_FOLDER>\test --output_path=<PATH_TO_ANNOTATIONS_FOLDER>\test.record

# 舉個例子 For example:
python3 generate_tfrecord.py --csv_input=C:\Users\sglvladi\Documents\TensorFlow\workspace\training_demo\annotations\train_labels.csv --output_path=C:\Users\sglvladi\Documents\TensorFlow\workspace\training_demo\annotations\train.record --img_path=C:\Users\sglvladi\Documents\TensorFlow\workspace\training_demo\images\train
python3 generate_tfrecord.py --csv_input=C:\Users\sglvladi\Documents\TensorFlow\workspace\training_demo\annotations\test_labels.csv --output_path=C:\Users\sglvladi\Documents\TensorFlow\workspace\training_demo\annotations\test.record --img_path=C:\Users\sglvladi\Documents\TensorFlow\workspace\training_demo\images\test

MacOS以及Linux用戶代碼參考:

1
2
3
4
5
6
7
#Linux
python3 generate_tfrecord.py --csv_input=/home/icthk/Desktop/Tensorflow/workspace/training_demo/annotations/train_labels.csv --output_path=/home/icthk/Desktop/Tensorflow/workspace/training_demo/annotations/train.record --img_path=/home/icthk/Desktop/Tensorflow/workspace/training_demo/images/train
python3 generate_tfrecord.py --csv_input=/home/icthk/Desktop/Tensorflow/workspace/training_demo/annotations/test_labels.csv --output_path=/home/icthk/Desktop/Tensorflow/workspace/training_demo/annotations/test.record --img_path=/home/icthk/Desktop/Tensorflow/workspace/training_demo/images/test

#MacOS
python3 generate_tfrecord.py --csv_input=/Users/icthk/Desktop/Tensorflow/workspace/training_demo/annotations/train_labels.csv --output_path=/Users/icthk/Desktop/Tensorflow/workspace/training_demo/annotations/train.record --img_path=/Users/icthk/Desktop/Tensorflow/workspace/training_demo/images/train
python3 generate_tfrecord.py --csv_input=/Users/icthk/Desktop/Tensorflow/workspace/training_demo/annotations/test_labels.csv --output_path=/Users/icthk/Desktop/Tensorflow/workspace/training_demo/annotations/test.record --img_path=/Users/icthk/Desktop/Tensorflow/workspace/training_demo/images/test

運行成功後,2個新文件test.record 和 train.record 將會在training_demo\annotations資料夾內生成

設定訓練配置

下載原模型資料夾

下一步,我們將會使用TensorFlow提供的原模型訓練自訂模型,這裡使用的是ssd_inception_v2_coco模型
因為它在準確度和回饋速度中取得一個較好的平衡,當然也有其他選擇,詳情請參考Detection Model Zoo
來到Detection Model Zoo尋找ssd_inception_v2_coco並點擊進行下載,下載好解壓放到 training_demo\pre-trained-model 目錄下


設定原模型配置文件

到training_demo/training 目錄下,新建原模型配置文件,貼上以下代碼, 命名為 ssd_inception_v2_coco.config
注意!第9、77、136行代碼需要根據用戶需要作調整,請仔細查看代碼中的注釋!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
# SSD with Inception v2 configuration for MSCOCO Dataset.
# Users should configure the fine_tune_checkpoint field in the train config as
# well as the label_map_path and input_path fields in the train_input_reader and
# eval_input_reader. Search for "PATH_TO_BE_CONFIGURED" to find the fields that
# should be configured.

model {
ssd {
num_classes: 2 # 標籤數目 Set this to the number of different label classes
box_coder {
faster_rcnn_box_coder {
y_scale: 10.0
x_scale: 10.0
height_scale: 5.0
width_scale: 5.0
}
}
matcher {
argmax_matcher {
matched_threshold: 0.5
unmatched_threshold: 0.5
ignore_thresholds: false
negatives_lower_than_unmatched: true
force_match_for_each_row: true
}
}
similarity_calculator {
iou_similarity {
}
}
anchor_generator {
ssd_anchor_generator {
num_layers: 6
min_scale: 0.2
max_scale: 0.95
aspect_ratios: 1.0
aspect_ratios: 2.0
aspect_ratios: 0.5
aspect_ratios: 3.0
aspect_ratios: 0.3333
reduce_boxes_in_lowest_layer: true
}
}
image_resizer {
fixed_shape_resizer {
height: 300
width: 300
}
}
box_predictor {
convolutional_box_predictor {
min_depth: 0
max_depth: 0
num_layers_before_predictor: 0
use_dropout: false
dropout_keep_probability: 0.8
kernel_size: 3
box_code_size: 4
apply_sigmoid_to_scores: false
conv_hyperparams {
activation: RELU_6,
regularizer {
l2_regularizer {
weight: 0.00004
}
}
initializer {
truncated_normal_initializer {
stddev: 0.03
mean: 0.0
}
}
}
}
}
feature_extractor {
type: 'ssd_inception_v2' # Set to the name of your chosen pre-trained model
min_depth: 16
depth_multiplier: 1.0
conv_hyperparams {
activation: RELU_6,
regularizer {
l2_regularizer {
weight: 0.00004
}
}
initializer {
truncated_normal_initializer {
stddev: 0.03
mean: 0.0
}
}
batch_norm {
train: true,
scale: true,
center: true,
decay: 0.9997,
epsilon: 0.001,
}
}
override_base_feature_extractor_hyperparams: true
}
loss {
classification_loss {
weighted_sigmoid {
}
}
localization_loss {
weighted_smooth_l1 {
}
}
hard_example_miner {
num_hard_examples: 3000
iou_threshold: 0.99
loss_type: CLASSIFICATION
max_negatives_per_positive: 3
min_negatives_per_image: 0
}
classification_weight: 1.0
localization_weight: 1.0
}
normalize_loss_by_num_matches: true
post_processing {
batch_non_max_suppression {
score_threshold: 1e-8
iou_threshold: 0.6
max_detections_per_class: 100
max_total_detections: 100
}
score_converter: SIGMOID
}
}
}

train_config: {
batch_size: 12 # Increase/Decrease this value depending on the available memory (Higher values require more memory and vice-versa)
optimizer {
rms_prop_optimizer: {
learning_rate: {
exponential_decay_learning_rate {
initial_learning_rate: 0.004
decay_steps: 800720
decay_factor: 0.95
}
}
momentum_optimizer_value: 0.9
decay: 0.9
epsilon: 1.0
}
}
fine_tune_checkpoint: "pre-trained-model/model.ckpt" # Path to extracted files of pre-trained model
from_detection_checkpoint: true
# Note: The below line limits the training process to 200K steps, which we
# empirically found to be sufficient enough to train the pets dataset. This
# effectively bypasses the learning rate schedule (the learning rate will
# never decay). Remove the below line to train indefinitely.
num_steps: 200000
data_augmentation_options {
random_horizontal_flip {
}
}
data_augmentation_options {
ssd_random_crop {
}
}
}

train_input_reader: {
tf_record_input_reader {
input_path: "annotations/train.record" # Path to training TFRecord file
}
label_map_path: "annotations/label_map.pbtxt" # Path to label map file
}

eval_config: {
num_examples: 8000
# Note: The below line limits the evaluation process to 10 evaluations.
# Remove the below line to evaluate indefinitely.
max_evals: 10
}

eval_input_reader: {
tf_record_input_reader {
input_path: "annotations/test.record" # Path to testing TFRecord
}
label_map_path: "annotations/label_map.pbtxt" # Path to label map file
shuffle: false
num_readers: 1
}

訓練模型

在開始訓練我們的模型之前,要先到 TensorFlow/models/research/object_detection/legacy/ 目錄下
複製 train.py 文件到我們的 training_demo資料夾下,我們需要它來訓練模型
接著,開啟終端機,cd到 training_demo 目錄下,運行以下代碼,開始訓練!

1
python3 train.py --logtostderr --train_dir=training/ --pipeline_config_path=training/ssd_inception_v2_coco.config

運行成功後便會出現以下畫面,模型開始訓練了!
若出現報錯等問題,請到下面或按這裡查詢解決方法

訓練進程

運行Tensorboard

TensorFlow提供了一個非常強大方便的功能 Tensorboard,可以讓用戶在一個可視化的環境下監測訓練進展
打開終端機cd到 training_demo 目錄下,運行以下代碼:

1
tensorboard --logdir=training

然後就會看到Tensorboard回饋了一個localhost端口地址,複製到瀏覽器便能打開Tensorboard了

監測訓練進程

在Tensorboard中,你可以很方便地查看Total Loss(在Losses section下)決定是否停止訓練
當Total Loss下降至0~1的範圍內,就代表你的模型已達到了不俗的準確率
當然它的實際數值也取值與你採用的模型、提供的樣本數量 及電腦效能配置等因素
通常,在標籤圖片數目不多的情況下,當TotalLoss的範圍開始固定/持續(到達極限),我便會停止訓練(好好愛護自己的電腦)

停止訓練

你可以留意模型訓練的checkpoint中斷訓練,它可以理解為儲存點(每訓練幾十步就會自動保存)
最新的儲存點則在第509步,我看到他的值已經很接近1了,我選擇在523步停止了訓練(ctrl+c/直接關掉終端機)
那麼我將會使用509步所保存的模型checkpoint作為我的AI模型了!



使用訓練後的模型進行物件識別

生成新模型配置文件

把training資料夾複製到 research/object_detection 目錄下,
然後開啟終端機運行以下代碼:
注意!第4行的代碼需要根據你的checkpoint文件名作更改!使用較大(最新)數字的文件作為模型

1
python3 export_inference_graph.py / --input_type image_tensor / --pipeline_config_path training/ssd_inception_v2_coco.config / --trained_checkpoint_prefix training/model.ckpt-509 / --output_directory new_model_graph

然後就會發現裡面新資料夾new_model_graph已經生成在object_detection目錄下了,這就是我們的新模型了

建立新模型label map

在 models/research/object_detection/data 目錄下,新建 label_map.pbtxt 文件,代碼如下:

1
2
3
4
5
6
7
8
9
item {
id: 1
name: 'Garen'
}

item {
id: 2
name: 'Darius'
}

修改物件識別運行文件

打開Jupyter Notebook來到models/research/object_detection目錄下
打開 object_detection_tutorial 文件,根據相應位置修改為以下代碼:

第一處:Model preparation - Variables

1
2
3
4
5
6
7
8
# What model to download.
MODEL_NAME = 'new_model_graph'

# Path to frozen detection graph. This is the actual model that is used for the object detection.
PATH_TO_FROZEN_GRAPH = MODEL_NAME + '/frozen_inference_graph.pb'

# List of the strings that is used to add correct label for each box.
PATH_TO_LABELS = os.path.join('data', 'label_map.pbtxt')

第二處:刪除Download Model中的代碼,直接整塊刪除便可


第三處:加入識別圖片,根據圖片數量修改Detection中的代碼
把圖片加入到 models/research/object_detection/test_images 資料夾內,命名圖片為”imageX.jpg”,X為數字。

然後後打開Jupyter Notebook,回到 object_detection_tutorial.ipynb 中,找到 “Detection”功能代碼所在位置
根據圖片名稱,修改其中第六行的range()內的數值,用我上面的例子,我只想檢測圖片image3.jpg 和image4.jpg
因此,我要修改為 range(3, 5),第一個數值是imageX中X的值 = 3,第二個數值則是第二張圖片imageX中的X+1 = 5



運行物件識別程式

打開object_detection_tutorial.ipynb
點擊”Cell”,選擇”Run All” 運行程式的所有代碼


運行成功,拉到最底看看識別結果!


報錯解決方法


ModuleNotFoundError: No module named ‘protos’報錯解決方法

若你是跟著我上一次mportError: cannot import name ‘string_int_label_map_pb2’報錯的解決方法做,這次你可能會出現這個問題
那麼這次,我們要把這個代碼還原,才能讓原模型文件讀取,進行訓練
來到object_detection/utils資料夾,開啟label_map_util.py把原先的代碼修改為以下代碼

1
2
# from protos import string_int_label_map_pb2 # 本來是這個
from object_detection.protos import string_int_label_map_pb2 #修改為這個

ImportError: cannot import name ‘string_int_label_map_pb2’報錯解決方法

呈上題,因為訓練和運行模型時,導入文件所用的代碼不一,所以訓練完畢後要把代碼還原
所以又要來到object_detection/utils資料夾,開啟label_map_util.py修改以下代碼




ImportError: cannot import name ‘input_reader_pb2’ from ‘object_detection.protos’報錯解決方法

在終端機 位置(Tensorflow/models/research)運行以下兩句代碼

1
2
protoc object_detection/protos/*.proto --python_out=.
export PYTHONPATH=$PYTHONPATH:`pwd`:`pwd`/slim

ModuleNotFoundError: No module named ‘object_detection’報錯解決方法

在終端機 位置(Tensorflow/models/research)運行以下兩句代碼

1
2
protoc object_detection/protos/*.proto --python_out=.
export PYTHONPATH=$PYTHONPATH:`pwd`:`pwd`/slim

ImportError: cannot import name ‘anchor_generator_pb2’ from ‘object_detection.protos’報錯解決方法

在終端機 位置(Tensorflow/models/research)運行以下兩句代碼

1
2
protoc object_detection/protos/*.proto --python_out=.
export PYTHONPATH=$PYTHONPATH:`pwd`:`pwd`/slim

Allocation of 1003520000 exceeds 10% of system memory報錯解決方法

這個問題會發現在訓練模型時,原因是系統內存不足以運行模型訓練
而解決方法則是減少訓練中的batch size,簡單來說就是減輕電腦每一步加載訓練的負荷,而訓練時間則會加長
打開training/ssd_inception_v2_coco.config 模型配置文件,修改 batch_size 數值(減少):

1
2
3
4
5
train_config: {
batch_size: 1 # Increase/Decrease this value depending on the available memory (Higher values require more memory and vice-versa)
optimizer {
...
...



即使不熟電腦/AI的你,也能嘗試使用AI技術

文章作者: icthk
文章鏈接: https://icthk.github.io/3_CustomObjectReconition.html
版權聲明: 本博客所有文章除特別聲明外,均採用 CC BY-NC-SA 4.0 許可協議。轉載請註明來自 ICTHK Blog