Object detection ๋ชจ๋ธ์ ์ด์ฉํ ๊ฐ์ฒด ํ์ง ๋ชจ๋ธ ๋ง๋ค๊ธฐ
SSD(Single Shot Multibox Detector) ์ฌ์ฉ
- ์ฐธ๊ณ Github: https://github.com/pierluigiferrari/ssd_keras
- ์ด์ฉ ๋ชจ๋
- python = 3.6
- tensorflow = 1.14.0
- keras = 2.2.4
-
11์ข ์ ์ต๋ฌด์ ๋ฐ์ดํฐ(csv, img)
- 11์ข : ๊ณ ํ, ๋์ปต, ๋ฐฑ์์ ํฉ์ต๋ฌด, ๋ถ์๊ด์ ํฉ์ต๋ฌด, ํฐ์ ํฉ์ต๋ฌด, ์ค์นผ๋ ๋งค์ปค์ฐ, ์ฒญ๊ธ๊ฐ์ต๋ฌด, ์นด๋ฉ๋กฏ๋งค์ปค์ฐ, ํ๊ธ๊ฐ์ต๋ฌด, ์ค์์ต๋ฌด, ํ์์ต๋ฌด
- ๊ฐ ์ต๋ฌด์ ์ข ํด๋์ csv, img ํด๋๋ก ๊ตฌ์ฑ๋์ด ์์
-
img
- 300x300 ์ด๋ฏธ์ง
-
csv
frame | xmin | xmax | ymin | ymax | class_id |
---|---|---|---|---|---|
0001_00000080.jpg | 22 | 89 | 64 | 152 | 1 |
0001_00000047.jpg | 40 | 124 | 46 | 160 | 1 |
0001_00000121.jpg | 170 | 242 | 70 | 159 | 1 |
-
frame: image file name
-
xmin, xmax, ymin, ymax: ์ต๋ฌด์ ๋จธ๋ฆฌ ์ด๋ฏธ์ง์ Anchor Box pixel ์์น๊ฐ
-
class_id: ์ต๋ฌด์ ์ข
-
csv, img ํ์ผ์ train, test, val๋ก ๋ถ๋ฆฌ
for filename in glob.iglob('๋ชจ๋8๋ฐ์ดํฐ(SSD_์ต๋ฌด์)/**/*.csv', recursive=True): csv = pd.read_csv(filename) if 'train' in filename: train_csv = train_csv.append(csv) for img in glob.iglob('๋ชจ๋8๋ฐ์ดํฐ(SSD_์ต๋ฌด์)/**/*.jpg', recursive=True): if img.split("\\")[-1] in csv['frame'].values: shutil.copy(img, "๋ชจ๋8๋ฐ์ดํฐ(SSD_์ต๋ฌด์)/train/") if 'test' in filename: test_csv = test_csv.append(csv) for img in glob.iglob('๋ชจ๋8๋ฐ์ดํฐ(SSD_์ต๋ฌด์)/**/*.jpg', recursive=True): if img.split("\\")[-1] in csv['frame'].values: shutil.copy(img, "๋ชจ๋8๋ฐ์ดํฐ(SSD_์ต๋ฌด์)/test/") if 'val' in filename: val_csv = val_csv.append(csv) for img in glob.iglob('๋ชจ๋8๋ฐ์ดํฐ(SSD_์ต๋ฌด์)/**/*.jpg', recursive=True): if img.split("\\")[-1] in csv['frame'].values: shutil.copy(img, "๋ชจ๋8๋ฐ์ดํฐ(SSD_์ต๋ฌด์)/val/")
-
h5 file ์์ฑ(test, val๋ ๋์ผํ๊ฒ ์งํ)
# 1: DataGenerator train_dataset = DataGenerator(load_images_into_memory=False, hdf5_dataset_path=None) # 2: Parse the image and label lists train_dataset.parse_csv(images_dir='data/train/', labels_filename='data/train/train.csv', input_format=['image_name', 'xmin', 'xmax', 'ymin', 'ymax', 'class_id'], include_classes='all') train_dataset.create_hdf5_dataset(file_path='saved_model/dataset_train.h5', resize=False, variable_image_size=True, verbose=True)
-
build model
K.clear_session() # Clear previous models from memory. model = ssd_300(image_size=(img_height, img_width, img_channels), n_classes=n_classes, mode='training', l2_regularization=0.0005, scales=scales, aspect_ratios_per_layer=aspect_ratios, two_boxes_for_ar1=two_boxes_for_ar1, steps=steps, offsets=offsets, clip_boxes=clip_boxes, variances=variances, normalize_coords=normalize_coords, subtract_mean=mean_color, swap_channels=swap_channels) weights_path = './saved_model/VGG_ILSVRC_16_layers_fc_reduced.h5' model.load_weights(weights_path, by_name=True) adam = Adam(lr=0.0001, beta_1=0.9, beta_2=0.999, epsilon=1e-08, decay=0.0) ssd_loss = SSDLoss(neg_pos_ratio=3, alpha=1.0) model.compile(optimizer=adam, loss=ssd_loss.compute_loss)
-
training
initial_epoch = 0 final_epoch = 40 steps_per_epoch = 100 history = model.fit_generator(generator=train_generator, steps_per_epoch=steps_per_epoch, epochs=final_epoch, callbacks=callbacks, validation_data=val_generator, validation_steps=ceil(val_dataset_size/batch_size), initial_epoch=initial_epoch)
-
optimizer: sgd -> adam
-
learning rate: 0.001 -> 0.0001
-
steps_per_epoch: 10 -> 100
-
batch_size, epoch
epoch = 10๊น์ง์ ๊ฒฐ๊ณผ ๊ทธ๋ํ
loss๊ฐ์ด ์๋ ดํ๊ณ ์์์ ์ ์ ์๋ค.
- epoch = 3, loss = 7.912, val_loss = 6.8487
๋ถ์๊ด์ ํฉ์ต๋ฌด๋ฅผ ๋ฐฑ์์ ํฉ์ต๋ฌด๋ก ์์ธกํ๋ ๊ฒ์ ๋ณด์, ์ ๋๋ก ์์ธก์ ํ์ง ๋ชปํ๊ณ ์์์ ์ ์ ์๋ค.
- epoch = 11, loss = 4.8239, val_loss = 4.2383
๋ถ์๊ด์ ํฉ์ต๋ฌด๋ฅผ ๋ถ์๊ด์ ํฉ์ต๋ฌด๋ก, ์นด๋ฉ๋กฏ๋งค์ปค์ฐ๋ฅผ ์นด๋ฉ๋กฏ๋งค์ปค์ฐ๋ก ๋ถ๋ฅํ๊ณ ์๋ ๊ฒ์ ๋ณด์ ์์ธก ์ฑ๋ฅ์ด ํฅ์๋ ๊ฒ์ ์ ์ ์๋ค.