A A
[CV] OpenImage Dataset์˜ Object Detection Inference Part.1 (with Keras-yolo)

Open Image Dataset์˜ Object Detection ํ•™์Šต ๋ฐ Inference

Open Image Dataset์—์„œ Football ๊ด€๋ จ Object, Fish๊ด€๋ จ Object๋ฅผ ์ถ”์ถœ ํ›„ ํ•™์Šต ๋ฐ์ดํ„ฐ ์„ธํŠธ ์ƒ์„ฑํ›„, ์ด๋ฅผ ์ด์šฉํ•˜์—ฌ Object Detection์„ ์ˆ˜ํ–‰ํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

๋ฐ์ดํ„ฐ ๋‹ค์šด๋กœ๋“œ ๋งํฌ
 

GitHub - chulminkw/DLCV

Contribute to chulminkw/DLCV development by creating an account on GitHub.

github.com


์ด๋ฒˆ์— Keras-yolo ํŒจํ‚ค์ง€, OpenImage Dataset์„ ์‚ฌ์šฉํ–ˆ์Šต๋‹ˆ๋‹ค.

# ํ˜„์žฌ ๋””๋ ‰ํ† ๋ฆฌ๋Š” /content์ด๋ฉฐ ์ด ๋””๋ ‰ํ† ๋ฆฌ๋ฅผ ๊ธฐ์ค€์œผ๋กœ ์‹ค์Šต์ฝ”๋“œ์™€ ๋ฐ์ดํ„ฐ๋ฅผ ๋‹ค์šด๋กœ๋“œ ํ•ฉ๋‹ˆ๋‹ค. 
!pwd
!rm -rf DLCV
!git clone https://github.com/chulminkw/DLCV.git

# DLCV ๋””๋ ‰ํ† ๋ฆฌ๊ฐ€ Download๋˜๊ณ  DLCV ๋ฐ‘์— Detection๊ณผ Segmentation ๋””๋ ‰ํ† ๋ฆฌ๊ฐ€ ์žˆ๋Š” ๊ฒƒ์„ ํ™•์ธ
!ls -lia 
!ls -lia DLCV
# Colab์—์„œ GPU ์ปค๋„ ์ ์šฉ์‹œ tensorflow 1.13์œผ๋กœ downgrade๊ฐ€ ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. 
# ๋•Œ๋ฌธ์— colab์—์„œ๋Š” Segmentation ํ•™์Šต ์‹œ tensorflow 1.15, keras 2.3 ์„ ์„ค์น˜ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.
# tensorflow 1.15์„ ์„ค์น˜ํ•ฉ๋‹ˆ๋‹ค. ์ž๋™์œผ๋กœ tensorflow 2.2๊ฐ€ 1.15๋กœ downgrade ๋ฉ๋‹ˆ๋‹ค. 
!pip install tensorflow-gpu==1.15.2 

# keras 2.3๋ฅผ ์„ค์น˜ํ•ฉ๋‹ˆ๋‹ค. 
!pip install keras==2.3.0

์ฃผ์˜์‚ฌํ•ญ

Keras-yolo3 ๋Š” Custom data ๋ฅผ train์‹œ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•˜๋Š”๋“ฑ tensorflow 1.15 ์™€ ์™„๋ฒฝํ•˜๊ฒŒ ํ˜ธํ™˜ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
๋•Œ๋ฌธ์— ์•„๋ž˜์™€ ๊ฐ™์ด DLCV github์—์„œ ์ˆ˜์ •๋œ init.py ๋ฅผ ๋‹ค์šด๋กœ๋“œ ๋ฐ›์•„์„œ keras์˜ backend์˜ init.py ๋ฅผ ์ˆ˜์ •ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
init.py๋Š” ๋ฐ˜๋“œ์‹œ import tensorflow, import keras ์ด์ „์— ์ˆ˜ํ–‰๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋งŒ์ผ tensorflow, keras ์„ค์น˜ํ•œ ๋’ค ์•„๋ž˜์˜ import tensorflow, import keras๋ฅผ ๋จผ์ € ์ˆ˜ํ–‰ํ•˜์˜€์œผ๋ฉด ๋‹ค์‹œ ์žฌ์‹œ์ž‘์„ ํ•œ ํ›„ init.py๋ฅผ ์ˆ˜์ •ํ•ฉ๋‹ˆ๋‹ค.
import os

# keras backend ๋””๋ ‰ํ† ๋ฆฌ ์ด๋™. 
os.chdir('/usr/local/lib/python3.6/dist-packages/keras/backend')

!rm -rf __init__.py
!rm -rf __pycache__

# ๊ธฐ์กด __init__.py ์‚ญ์ œํ•˜๊ณ  ์ƒˆ๋กœ์šด __init__.py๋ฅผ download 
!wget https://raw.githubusercontent.com/chulminkw/DLCV/master/colab_tf115_modify_files/__init__.py
# tensorflow๋Š” 1.15, keras๋Š” 2.3 ๋ฒ„์ „ ํ™•์ธ
# GPU๊ฐ€ ์„ธํŒ…๋˜์–ด ์žˆ์ง€ ์•Š์œผ๋ฉด ์ƒ๋‹จ ๋ฉ”๋‰ด์—์„œ ๋Ÿฐํƒ€์ž„->๋Ÿฐํƒ€์ž„ ์œ ํ˜• ๋ณ€๊ฒฝ์—์„œ GPU๋ฅผ ์„ ํƒํ•œ ํ›„ ๋Ÿฐํƒ€์ž„ ๋‹ค์‹œ ์‹œ์ž‘์„ ์„ ํƒํ•˜๊ณ  ์ฒ˜์Œ ๋ถ€ํ„ฐ์ธ tensorflow, keras ์„ค์น˜ ๋ถ€ํ„ฐ ๋‹ค์‹œ ์‹œ์ž‘. 
import tensorflow as tf
import keras

print(tf.__version__)
print(keras.__version__)

# gpu๊ฐ€ ์„ธํŒ…๋“œ์–ด ์žˆ๋Š”์ง€ ํ™•์ธ. 
tf.test.gpu_device_name()
Tip: ์ฝ”๋žฉ ๋ฒ„์ „์€ ์•„๋ž˜๋ฅผ ์ด์šฉํ•˜์—ฌ keras-yolo3 ํŒจํ‚ค์ง€๋ฅผ download ํ•˜์—ฌ /content/DLCV/Detection/yolo ๋ฐ‘์— ์„ค์น˜ํ•ฉ๋‹ˆ๋‹ค.
%cd /content/DLCV/Detection/yolo
!git clone https://github.com/qqwweee/keras-yolo3.git
!ls -lia /content/DLCV/Detection/yolo/keras-yolo3

pretrained ๋ชจ๋ธ ์žฌ์ƒ์„ฑ ๋ฐ font ๋””๋ ‰ํ† ๋ฆฌ ๊ต์ฒด (Colab Version)

  • ์ฝ”๋žฉ์œผ๋กœ ๋Œ๋ฆฌ๋Š” ๊ฒฝ์šฐ์—๋Š” ๋‹ค์‹œ model_data ๋ฐ‘์— coco dataset๋กœ pretrained ๋œ yolov3.weights ํŒŒ์ผ์„ yolo.h5 ํŒŒ์ผ๋กœ ๋ณ€๊ฒฝํ•ด ์ค˜์•ผ ํ•ฉ๋‹ˆ๋‹ค.
  • keras-yolo3์˜ font ๋””๋ ‰ํ† ๋ฆฌ๋„ ์žฌ ๊ต์ฒด ํ•ฉ๋‹ˆ๋‹ค.
# ์ฝ”๋žฉ ๋ฒ„์ „์€ ์•„๋ž˜๋ฅผ ์ด์šฉํ•˜์—ฌ yolov3.weights ํŒŒ์ผ์„ download ๋ฐ›๊ณ , convert.py ๋ฅผ ์ˆ˜ํ–‰ํ•˜์—ฌ model_data ๋ฐ‘์— yolo.h5 ํŒŒ์ผ ์ƒ์„ฑ ์ˆ˜ํ–‰. 
%cd /content/DLCV/Detection/yolo/keras-yolo3 
# yolo ๊ณต์‹ ์‚ฌ์ดํŠธ์—์„œ download์‹œ download ์†๋„๊ฐ€ ์•ฝ 25๋ถ„ ์ •๋„ ์†Œ์š”๋จ. github์—์„œ ๋‹ค์šด๋กœ๋“œ ์š”๋ง. 
# !wget  https://pjreddie.com/media/files/yolov3.weights
# github์—์„œ ๋‹ค์šด๋กœ๋“œ
!wget https://github.com/chulminkw/DLCV/releases/download/1.0/yolov3.weights
# yolov3.weights๋ฅผ keras-yolo3์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก yolo.h5 ๋กœ ๋ณ€ํ™˜
!python convert.py yolov3.cfg yolov3.weights model_data/yolo.h5
# model_data ๋ฐ‘์— yolo.h5 ํŒŒ์ผ์ด ์ƒ์„ฑ๋˜์—ˆ๋Š”์ง€ ํ™•์ธ. 
!ls /content/DLCV/Detection/yolo/keras-yolo3/model_data
# yolo.detect_image() ๋ฉ”์†Œ๋“œ๋Š” PIL package๋ฅผ ์ด์šฉํ•˜์—ฌ image ์ž‘์—… ์ˆ˜ํ–‰. keras-yolo3/font ๋””๋ ‰ํ† ๋ฆฌ๋ฅผ ์ƒ์œ„ ๋””๋ ‰ํ† ๋ฆฌ๋กœ ๋ณต์‚ฌ ํ•ด์•ผํ•จ.  
%cd /content/DLCV/Detection/yolo
!cp -rf keras-yolo3/font ./font

OID Toolkit์„ ํ†ตํ•ด ๋งŒ๋“ค์–ด์ง„ ๋ฐ์ดํ„ฐ ์„ธํŠธ๋ฅผ ๋‹ค์šด๋กœ๋“œ ํ•ฉ๋‹ˆ๋‹ค.

  • ๋งŒ๋“ค์–ด์ง„ ballnfish.tar ํŒŒ์ผ์„ ๋‹ค์šด๋กœ๋“œ ํ•œ ๋’ค ์ด๋ฅผ ์ด์šฉํ•˜์—ฌ ํ•™์Šต ํ•ฉ๋‹ˆ๋‹ค.
# ballnfish.tar ํŒŒ์ผ์„ ๊ฐ•์˜์˜ github์—์„œ download ํ•œ ๋’ค ์••์ถ•์„ ํ’€๋ฉด
# /content/DLCV/data/ballnfish ๋””๋ ‰ํ† ๋ฆฌ๋กœ annotations, images ๋””๋ ‰ํ† ๋ฆฌ์™€ ๊ด€๋ จ ํŒŒ์ผ๋“ค์ด ์ƒ์„ฑ ๋ฉ๋‹ˆ๋‹ค. 
%cd /content/DLCV/data
!wget https://github.com/chulminkw/DLCV/releases/download/1.0/ballnfish.tar
!tar -xvf ballnfish.tar > /dev/null 2>&1
import os
from pathlib import Path

# ์ฝ”๋žฉ ํ™˜๊ฒฝ์—์„œ๋Š” ํ™ˆ ๋””๋ ‰ํ† ๋ฆฌ๋ฅผ '/content'๋กœ ์„ค์ •
HOME_DIR = '/content'

# ์ฃผ์„๊ณผ ์ด๋ฏธ์ง€ ๋””๋ ‰ํ† ๋ฆฌ ๊ฒฝ๋กœ ์„ค์ •
ANNO_DIR = os.path.join(HOME_DIR, 'DLCV/data/ballnfish/annotations')
IMAGE_DIR = os.path.join(HOME_DIR, 'DLCV/data/ballnfish/images')
print(ANNO_DIR)

# ์ฃผ์„ ๋””๋ ‰ํ† ๋ฆฌ์˜ ํŒŒ์ผ ๋ชฉ๋ก๊ณผ ๊ฐœ์ˆ˜ ์ถœ๋ ฅ
files = os.listdir(ANNO_DIR)
print('ํŒŒ์ผ ๊ฐœ์ˆ˜๋Š”:', len(files))
print(files)
  • Open Image Dataset์˜ ์ฃผ์„๊ณผ ์ด๋ฏธ์ง€ ๋””๋ ‰ํ† ๋ฆฌ๋ฅผ ์„ค์ •ํ•˜๊ณ , ์ฃผ์„ ๋””๋ ‰ํ† ๋ฆฌ ๋‚ด ํŒŒ์ผ์˜ ๊ฐœ์ˆ˜์™€ ์ด๋ฆ„์„ ์ถœ๋ ฅํ•˜์—ฌ ๋ฐ์ดํ„ฐ ์ค€๋น„ ์ƒํƒœ๋ฅผ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.

# ์•„๋ž˜๋Š” ์œ„์—์„œ ์ถœ๋ ฅ๋œ ์ ๋‹นํ•œ xml ํŒŒ์ผ๋กœ ๋ณ€๊ฒฝ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. 
!cat /content/DLCV/data/ballnfish/annotations/13825baad5531265.xml

  • ์ฃผ์–ด์ง„ ๊ฒฝ๋กœ์˜ XML ํŒŒ์ผ๋“ค์„ ์ฝ์–ด ๊ฐ ๊ฐ์ฒด์˜ ๋ฐ”์šด๋”ฉ ๋ฐ•์Šค์™€ ํด๋ž˜์Šค ์ •๋ณด๋ฅผ CSV ํŒŒ์ผ๋กœ ๋ณ€ํ™˜ํ•ฉ๋‹ˆ๋‹ค.
  • ํด๋ž˜์Šค ์ด๋ฆ„์„ ID๋กœ ๋งคํ•‘ํ•˜๊ณ , ์ด๋ฏธ์ง€ ๊ฒฝ๋กœ์™€ ๊ฐ์ฒด ์ •๋ณด๋ฅผ ํ•œ ์ค„์— ๊ธฐ๋กํ•˜์—ฌ ๊ฐ์ฒด ๊ฒ€์ถœ ๋ชจ๋ธ ํ•™์Šต์— ํ•„์š”ํ•œ ๋ฐ์ดํ„ฐ๋ฅผ ์ค€๋น„ํ•ฉ๋‹ˆ๋‹ค.
import glob
import xml.etree.ElementTree as ET

# ํด๋ž˜์Šค ์ด๋ฆ„๊ณผ ID ๋งคํ•‘
classes_map = {'Football':0, 'Football_helmet':1, 'Fish':2, 'Shark':3, 'Shellfish':4 }

def xml_to_csv(path, output_filename):
    xml_list = []
    # ์ถœ๋ ฅ CSV ํŒŒ์ผ ์—ด๊ธฐ
    with open(output_filename, "w") as train_csv_file:
        # ์ง€์ •๋œ ๊ฒฝ๋กœ์˜ ๋ชจ๋“  XML ํŒŒ์ผ ์ˆœํšŒ
        for xml_file in glob.glob(path + '/*.xml'):
            # XML ํŒŒ์ผ ํŒŒ์‹ฑ
            tree = ET.parse(xml_file)
            root = tree.getroot()
            print('xml file:', xml_file)
            # ์ด๋ฏธ์ง€ ํŒŒ์ผ ๊ฒฝ๋กœ ๊ฐ€์ ธ์˜ค๊ธฐ
            full_image_name = os.path.join(IMAGE_DIR, root.find('filename').text)
            value_str_list = ' '
            # ๋ชจ๋“  object ์š”์†Œ ์ˆœํšŒ
            for obj in root.findall('object'):
                xmlbox = obj.find('bndbox')
                class_name = obj.find('name').text
                x1 = int(xmlbox.find('xmin').text)
                y1 = int(xmlbox.find('ymin').text)
                x2 = int(xmlbox.find('xmax').text)
                y2 = int(xmlbox.find('ymax').text)
                # ํด๋ž˜์Šค ID ๋งคํ•‘
                class_id = classes_map[class_name]
                # ๊ฐ์ฒด ์ •๋ณด ๋ฌธ์ž์—ด ์ƒ์„ฑ
                value_str = ('{0},{1},{2},{3},{4}').format(x1, y1, x2, y2, class_id)
                # ๊ฐ์ฒด ์ •๋ณด ๋ˆ„์ 
                value_str_list += value_str + ' '
        
            # ์ด๋ฏธ์ง€ ๊ฒฝ๋กœ์™€ ๊ฐ์ฒด ์ •๋ณด CSV์— ์ž‘์„ฑ
            train_csv_file.write(full_image_name + ' ' + value_str_list + '\n')
        # XML ํŒŒ์ผ ์ฒ˜๋ฆฌ ์ข…๋ฃŒ
xml_to_csv(ANNO_DIR, os.path.join(ANNO_DIR,'ballnfish_anno.csv'))
print(os.path.join(ANNO_DIR,'ballnfish_anno.csv'))
!cat /content/DLCV/data/ballnfish/annotations/ballnfish_anno.csv

์—ฌ๊ธฐ์„œ ๋ณด๋ฉด ์‚ฌ์ง„์ˆซ์ž.jpg ๋’ค์— ์žˆ๋Š” ์ˆซ์ž๋“ค์˜ ์˜๋ฏธ๋Š”, format(x1, y1, x2, y2, class_id) - ์ขŒ์ƒ๋‹จ, ์šฐํ•˜๋‹จ ์ขŒํ‘œ
Class id ('Football':0, 'Football_helmet':1, 'Fish':2, 'Shark':3, 'Shellfish':4)๋ฅผ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.

๋ฐ์ดํ„ฐ์…‹ ์‚ฌ์ง„ ๋ณด๊ธฐ

import cv2
import matplotlib.pyplot as plt
%matplotlib inline

default_dir = '/content'
# 9c27811a78b74a48.jpg ๋Š” images ๋””๋ ‰ํ† ๋ฆฌ์— ์žˆ๋Š” ์ž„์˜ ํŒŒ์ผ๋กœ ๋ฐ”๋€Œ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. 
plt.imshow(cv2.cvtColor(cv2.imread(os.path.join(default_dir, 'DLCV/data/ballnfish/images/9c27811a78b74a48.jpg')), cv2.COLOR_BGR2RGB))
  • ์‹คํ–‰ ์˜ˆ์ œ


์‹คํ–‰ ๋ชจ๋“ˆ ๋กœ๋”ฉ

import numpy as np
import keras.backend as K
from keras.layers import Input, Lambda
from keras.models import Model
from keras.optimizers import Adam
from keras.callbacks import TensorBoard, ModelCheckpoint, ReduceLROnPlateau, EarlyStopping
import sys, os

import os

# ์ฝ”๋žฉ ์œผ๋กœ ๋Œ๋ฆฌ๋Š” ๊ฒฝ์šฐ์—์€ ์•„๋ž˜์™€ ๊ฐ™์ด ์ ˆ๋Œ€ ๊ฒฝ๋กœ๋ฅผ ์ง€์ •ํ•˜์—ฌ Local Package ์ง€์ •. 
default_dir = '/content/DLCV'
default_yolo_dir = os.path.join(default_dir, 'Detection/yolo')

LOCAL_PACKAGE_DIR = os.path.abspath(os.path.join(default_yolo_dir,'keras-yolo3'))
print(LOCAL_PACKAGE_DIR)
sys.path.append(LOCAL_PACKAGE_DIR)

from yolo3.model import preprocess_true_boxes, yolo_body, tiny_yolo_body, yolo_loss
from yolo3.utils import get_random_data
  • ๋˜ํ•œ colab ๋ฒ„์ „์€ ์•„๋ž˜ ๋ช…๋ น์–ด๋กœ ballnfish_classes.txt ๋ฅผ ์ˆ˜์ •
import os

# ์ฝ”๋žฉ ํ™˜๊ฒฝ์—์„œ BASE_DIR๊ณผ classes_path ์„ค์ •
BASE_DIR = os.path.join(HOME_DIR, 'DLCV/Detection/yolo/keras-yolo3')
classes_path = os.path.join(BASE_DIR, 'model_data/ballnfish_classes.txt')

# ํด๋ž˜์Šค ์ด๋ฆ„์„ ํŒŒ์ผ์— ์ž‘์„ฑ
with open(classes_path, "w") as f:
    f.write("Football\n")
    f.write("Football_Helmet\n")
    f.write("Fish\n")
    f.write("Shark\n")
    f.write("Shell_Fish\n")

# ์ž‘์„ฑ๋œ ํด๋ž˜์Šค ํŒŒ์ผ ๋‚ด์šฉ ํ™•์ธ
!cat /content/DLCV/Detection/yolo/keras-yolo3/model_data/ballnfish_classes.txt
from train import get_classes, get_anchors
from train import create_model, data_generator, data_generator_wrapper

# BASE_DIR ์„ค์ •: YOLO ๋ชจ๋ธ ๊ด€๋ จ ํŒŒ์ผ๋“ค์ด ์žˆ๋Š” ๋””๋ ‰ํ† ๋ฆฌ
BASE_DIR = os.path.join(HOME_DIR, 'DLCV/Detection/yolo/keras-yolo3')

# ํ•™์Šต์„ ์œ„ํ•œ ๊ฒฝ๋กœ ์„ค์ •
annotation_path = os.path.join(ANNO_DIR, 'ballnfish_anno.csv')  # ์ฃผ์„ ํŒŒ์ผ ๊ฒฝ๋กœ
log_dir = os.path.join(BASE_DIR, 'snapshots/ballnfish/')         # ํ•™์Šต๋œ ๋ชจ๋ธ ์ €์žฅ ๊ฒฝ๋กœ
classes_path = os.path.join(BASE_DIR, 'model_data/ballnfish_classes.txt')  # ํด๋ž˜์Šค ํŒŒ์ผ ๊ฒฝ๋กœ
anchors_path = os.path.join(BASE_DIR, 'model_data/yolo_anchors.txt')        # ์•ต์ปค ํŒŒ์ผ ๊ฒฝ๋กœ

# ํด๋ž˜์Šค ์ด๋ฆ„๊ณผ ์ˆ˜ ๋ถˆ๋Ÿฌ์˜ค๊ธฐ
class_names = get_classes(classes_path)
num_classes = len(class_names)

# ์•ต์ปค ๋ฐ•์Šค ๋ถˆ๋Ÿฌ์˜ค๊ธฐ
anchors = get_anchors(anchors_path)

# ํด๋ž˜์Šค ์ด๋ฆ„, ํด๋ž˜์Šค ์ˆ˜ ๋ฐ ์•ต์ปค ๋ฐ•์Šค ์ถœ๋ ฅ
print(class_names, num_classes)
print(anchors)
  • ์ถœ๋ ฅ๋œ ๊ฒฐ๊ณผ๊ฐ’ (์ƒ๋‹จ์€ ํด๋ž˜์Šค ๋ช… & ๊ฐœ์ˆ˜), ํ•˜๋‹จ์˜ ์ˆซ์ž๋“ค์€ Anchor Box๋“ค์˜ ์ •๋ณด๋ฅผ ์˜๋ฏธ.


yolo ๋ชจ๋ธ ํ•™์Šต์„ ์œ„ํ•œ ์ „๋ฐ˜์ ์ธ ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ config ํด๋ž˜์Šค๋กœ ์„ค์ •ํ•˜๊ณ  ํ•„์š”์‹œ ์ด๋ฅผ ์ˆ˜์ •ํ•˜์—ฌ ํ•™์Šต.

์ฆ‰, ์ด๋ง์€ config๋ฅผ ํด๋ž˜์Šคํ™” ํ•œ๋‹ค๋Š” ์˜๋ฏธ์ž…๋‹ˆ๋‹ค.
# csv annotation ํŒŒ์ผ์„ ์ฝ์–ด์„œ lines ๋ฆฌ์ŠคํŠธ๋กœ ๋งŒ๋“ฌ. 
with open(annotation_path) as f:
    lines = f.readlines()

class config:
    #tiny yolo๋กœ ๋ชจ๋ธ๋กœ ์ดˆ๊ธฐ weight ํ•™์Šต ์›ํ•  ์‹œ ์•„๋ž˜๋ฅผ tiny-yolo.h5๋กœ ์ˆ˜์ •. 
    initial_weights_path=os.path.join(BASE_DIR, 'model_data/yolo.h5' )
    # input_shape๋Š” ๊ณ ์ •. 
    input_shape=(416, 416)
    # epochs๋Š” freeze, unfreeze 2 step์— ๋”ฐ๋ผ ์„ค์ •. 
    first_epochs=50
    first_initial_epochs=0
    second_epochs=100
    second_initial_epochs=50
    # ํ•™์Šต์‹œ batch size, train,valid๊ฑด์ˆ˜, epoch steps ํšŸ์ˆ˜  
    batch_size = 4
    val_split = 0.1   
    num_val = int(len(lines)*val_split)
    num_train = len(lines) - num_val
    train_epoch_steps = num_train//batch_size 
    val_epoch_steps =  num_val//batch_size
    
    anchors = get_anchors(anchors_path)
    class_names = get_classes(classes_path)
    num_classes = len(class_names)
    # epoch์‹œ ์ €์žฅ๋œ weight ํŒŒ์ผ ๋””๋ ‰ํ† ๋ฆฌ 
    log_dir = os.path.join(BASE_DIR, 'snapshots/ballnfish/')
    
print('Class name:', config.class_names,'\nNum classes:', config.num_classes)

 

csv ํŒŒ์ผ์„ ์ž…๋ ฅ ๋ฐ›์•„์„œ train ๋ฐ์ดํ„ฐ์™€ valid ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ๋ฅผ ์œ„ํ•œ data_generator_wrapper๊ฐ์ฒด๋ฅผ ๊ฐ๊ฐ ์ƒ์„ฑ.

  • train์šฉ, valid ์šฉ data_generator_wrapper๋Š” Yolo ๋ชจ๋ธ์˜ fit_generator()ํ•™์Šต์‹œ ์ธ์ž๋กœ ์ž…๋ ฅ๋จ.
def create_generator(lines):
    # ํ›ˆ๋ จ ๋ฐ์ดํ„ฐ ์ƒ์„ฑ๊ธฐ ์ƒ์„ฑ (๋ฐ์ดํ„ฐ์˜ ์ฒ˜์Œ config.num_train ๊ฐœ ์‚ฌ์šฉ)
    train_data_generator = data_generator_wrapper(
        lines[:config.num_train],
        config.batch_size,
        config.input_shape,
        config.anchors,
        config.num_classes
    )
    
    # ๊ฒ€์ฆ ๋ฐ์ดํ„ฐ ์ƒ์„ฑ๊ธฐ ์ƒ์„ฑ (๋‚˜๋จธ์ง€ ๋ฐ์ดํ„ฐ ์‚ฌ์šฉ)
    valid_data_generator = data_generator_wrapper(
        lines[config.num_train:],
        config.batch_size,
        config.input_shape,
        config.anchors,
        config.num_classes
    )
    
    # ํ›ˆ๋ จ ๋ฐ ๊ฒ€์ฆ ๋ฐ์ดํ„ฐ ์ƒ์„ฑ๊ธฐ ๋ฐ˜ํ™˜
    return train_data_generator, valid_data_generator
  • YOLO ๋ชจ๋ธ ๋˜๋Š” tiny yolo ๋ชจ๋ธ ๋ฐ˜ํ™˜. ์ดˆ๊ธฐ weight๊ฐ’์€ pretrained๋œ yolo weight๊ฐ’์œผ๋กœ ํ• ๋‹น.
# anchor ๊ฐœ์ˆ˜์— ๋”ฐ๋ผ Tiny YOLO ๋ชจ๋ธ ๋˜๋Š” ์ผ๋ฐ˜ YOLO ๋ชจ๋ธ์„ ์ƒ์„ฑํ•˜๋Š” ํ•จ์ˆ˜
def create_yolo_model():
    # ์•ต์ปค ๊ฐœ์ˆ˜๊ฐ€ 6๊ฐœ์ด๋ฉด Tiny YOLO ๋ฒ„์ „์œผ๋กœ ๊ฐ„์ฃผ
    is_tiny_version = len(config.anchors) == 6 
    if is_tiny_version:
        # Tiny YOLO ๋ชจ๋ธ ์ƒ์„ฑ
        model = create_tiny_model(
            config.input_shape, 
            config.anchors, 
            config.num_classes, 
            freeze_body=2, 
            weights_path=config.initial_weights_path
        )
    else:
        # ์ผ๋ฐ˜ YOLO ๋ชจ๋ธ ์ƒ์„ฑ
        model = create_model(
            config.input_shape, 
            config.anchors, 
            config.num_classes, 
            freeze_body=2, 
            weights_path=config.initial_weights_path
        )
        
    return model
  • ์•ต์ปค์˜ ๊ฐœ์ˆ˜์— ๋”ฐ๋ผ Tiny YOLO ๋ชจ๋ธ ๋˜๋Š” ์ผ๋ฐ˜ YOLO ๋ชจ๋ธ์„ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.
  • ์•ต์ปค๊ฐ€ 6๊ฐœ์ธ ๊ฒฝ์šฐ Tiny YOLO๋ฅผ ์‚ฌ์šฉํ•˜๊ณ , ๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด ํ‘œ์ค€ YOLO ๋ชจ๋ธ์„ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.
# Tensorboard, ModelCheckpoint, ReduceLROnPlateau, EarlyStopping callback ๋ฐ˜ํ™˜
def create_callbacks():
    logging = TensorBoard(log_dir=config.log_dir)
    checkpoint = ModelCheckpoint(config.log_dir + 'ep{epoch:03d}-loss{loss:.3f}-val_loss{val_loss:.3f}.h5',
        monitor='val_loss', save_weights_only=True, save_best_only=True, period=3)
    reduce_lr = ReduceLROnPlateau(monitor='val_loss', factor=0.1, patience=3, verbose=1)
    early_stopping = EarlyStopping(monitor='val_loss', min_delta=0, patience=10, verbose=1)
    
    #๊ฐœ๋ณ„ callback๋“ค์„ ํ•œ๊บผ๋ฒˆ์— list๋กœ ๋ฌถ์–ด์„œ ๋ฐ˜ํ™˜
    return [logging, checkpoint, reduce_lr, early_stopping]

ํ•™์Šต ์ˆ˜ํ–‰

# create_generator(), create_model(), create_callbacks() ์ˆ˜ํ–‰. 
train_data_generator, valid_data_generator = create_generator(lines)
ballnfish_model = create_yolo_model()
callbacks_list = create_callbacks()

# ์ตœ์ดˆ ๋ชจ๋ธ์€ ์ฃผ์š” layer๊ฐ€ freeze๋˜์–ด ์žˆ์Œ. ์•ˆ์ •์ ์ธ loss๋ฅผ ํ™•๋ณดํ•˜๊ธฐ ์œ„ํ•ด ์ฃผ์š” layer๋ฅผ freezeํ•œ ์ƒํƒœ๋กœ ๋จผ์ € ํ•™์Šต. 
print('First train ์‹œ์ž‘')
ballnfish_model.compile(optimizer=Adam(lr=1e-3), loss={'yolo_loss': lambda y_true, y_pred: y_pred})

# ์ฒซ ๋ฒˆ์งธ ๋‹จ๊ณ„ ํ•™์Šต ์ˆ˜ํ–‰
ballnfish_model.fit_generator(
    train_data_generator, 
    steps_per_epoch=config.train_epoch_steps,
    validation_data=valid_data_generator, 
    validation_steps=config.val_epoch_steps,
    epochs=config.first_epochs, 
    initial_epoch=config.first_initial_epochs, 
    callbacks=callbacks_list
)

# 1๋‹จ๊ณ„ ํ•™์Šต ์™„๋ฃŒ ๋ชจ๋ธ ์ €์žฅ
ballnfish_model.save_weights(os.path.join(log_dir, 'trained_weights_stage_1.h5'))

# ๋ชจ๋“  layer๋ฅผ trainable=True๋กœ ์„ค์ •ํ•˜๊ณ  ์ถ”๊ฐ€ ํ•™์Šต ์ˆ˜ํ–‰
for layer in ballnfish_model.layers:
    layer.trainable = True

print('Second train ์‹œ์ž‘')
ballnfish_model.compile(optimizer=Adam(lr=1e-4), loss={'yolo_loss': lambda y_true, y_pred: y_pred}) 

# ๋‘ ๋ฒˆ์งธ ๋‹จ๊ณ„ ํ•™์Šต ์ˆ˜ํ–‰
ballnfish_model.fit_generator(
    train_data_generator, 
    steps_per_epoch=config.train_epoch_steps,
    validation_data=valid_data_generator, 
    validation_steps=config.val_epoch_steps,
    epochs=config.second_epochs, 
    initial_epoch=config.second_initial_epochs,
    callbacks=callbacks_list
)

# ์ตœ์ข… ํ•™์Šต ์™„๋ฃŒ ๋ชจ๋ธ ์ €์žฅ
ballnfish_model.save_weights(os.path.join(log_dir, 'trained_weights_final.h5'))
  • ์ฒซ ๋ฒˆ์งธ ๋‹จ๊ณ„์—์„œ๋Š” ์ฃผ์š” ๋ ˆ์ด์–ด๋ฅผ ๊ณ ์ •(freeze)ํ•œ ์ƒํƒœ๋กœ ๋ชจ๋ธ์„ ํ•™์Šตํ•˜์—ฌ ์•ˆ์ •์ ์ธ ์†์‹ค์„ ํ™•๋ณดํ•˜๊ณ , ํ•™์Šต์ด ์™„๋ฃŒ๋˜๋ฉด ๋ชจ๋“  ๋ ˆ์ด์–ด๋ฅผ ํ•™์Šต ๊ฐ€๋Šฅ(trainable) ์ƒํƒœ์œผ๋กœ ์„ค์ •ํ•œ ํ›„ ์ถ”๊ฐ€๋กœ ํ•™์Šต์„ ์ง„ํ–‰ํ•ฉ๋‹ˆ๋‹ค.
  • ๊ฐ ๋‹จ๊ณ„ ํ›„์— ๋ชจ๋ธ์˜ ๊ฐ€์ค‘์น˜๋ฅผ ์ €์žฅํ•˜์—ฌ ๋‚˜์ค‘์— ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•ฉ๋‹ˆ๋‹ค.

์ตœ์ข… ํ•™์Šต๋œ ๋ชจ๋ธ์„ ๋กœ๋”ฉํ•˜์—ฌ Object Detection ์ˆ˜ํ–‰.

from yolo import YOLO
#keras-yolo์—์„œ image์ฒ˜๋ฆฌ๋ฅผ ์ฃผ์š” PIL๋กœ ์ˆ˜ํ–‰. 
from PIL import Image

# ์ฝ”๋žฉ ๋ฒ„์ „์€ ์•„๋ž˜์™€ ๊ฐ™์ด ์ ˆ๋Œ€ ๊ฒฝ๋กœ๋ฅผ ์ง€์ •ํ•˜์—ฌ Local Package ์ง€์ •. 
default_dir = '/content/DLCV'
default_yolo_dir = os.path.join(default_dir, 'Detection/yolo')

LOCAL_PACKAGE_DIR = os.path.abspath(os.path.join(default_yolo_dir,'keras-yolo3'))
sys.path.append(LOCAL_PACKAGE_DIR)

ballnfish_yolo = YOLO(model_path='/content/DLCV/Detection/yolo/keras-yolo3/snapshots/ballnfish/trained_weights_final.h5',
            anchors_path='/content/DLCV/Detection/yolo/keras-yolo3/model_data/yolo_anchors.txt',
            classes_path='/content/DLCV/Detection/yolo/keras-yolo3/model_data/ballnfish_classes.txt')

์ด๋ฏธ์ง€ Object Detection.

%cd /content/DLCV/data/ballnfish
!ls annotations
# ์•„๋ž˜ football_list๋Š” ์ ์ ˆํ•œ jpg ํŒŒ์ผ๋ช…์œผ๋กœ ๋ณ€๊ฒฝ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. 
football_list = ['f1b492a9bce3ac9a.jpg', '1e6ff631bb0c198b.jpg', '97ac013310bda756.jpg',
                'e5b1646c395aecfd.jpg', '53ef241dad498f6c.jpg', '02ccbf5ddaaecedb.jpg' ]
for image_name in football_list:
    img = Image.open(os.path.join(IMAGE_DIR, image_name))
    detected_img = ballnfish_yolo.detect_image(img)
    plt.figure(figsize=(8, 8))
    plt.imshow(detected_img)
  • Object Detection ๊ฒฐ๊ณผ

# ์•„๋ž˜ helmet_list๋Š” ์ ์ ˆํ•œ jpg ํŒŒ์ผ๋ช…์œผ๋กœ ๋ณ€๊ฒฝ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. 
helmet_list = ['1fed5c930211c6e0.jpg', '011a59a160d7a091.jpg', 'd39b46aa4bc0c165.jpg', '7e9eb7eba80e34e7.jpg', '9c27811a78b74a48.jpg']
for image_name in helmet_list:
    img = Image.open(os.path.join(IMAGE_DIR, image_name))
    detected_img = ballnfish_yolo.detect_image(img)
    plt.figure(figsize=(8, 8))
    plt.imshow(detected_img)
  • Object Detection ๊ฒฐ๊ณผ

# ์•„๋ž˜ fish_list๋Š” ์ ์ ˆํ•œ jpg ํŒŒ์ผ๋ช…์œผ๋กœ ๋ณ€๊ฒฝ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
fish_list = ['25e42c55bfcbaa88.jpg', 'a571e4cdcfbcb79e.jpg', '872c435491f2b4d3.jpg', 
             'bebac23c45451d93.jpg', 'eba7caf07a26829b.jpg', 'dc607a2989bdc9dc.jpg' ]
for image_name in fish_list:
    img = Image.open(os.path.join(IMAGE_DIR, image_name))
    detected_img = ballnfish_yolo.detect_image(img)
    plt.figure(figsize=(8, 8))
    plt.imshow(detected_img)
  • Object Detection ๊ฒฐ๊ณผ (์ฒซ๋ฒˆ์งธ, 3๋ฒˆ์งธ ์‚ฌ์ง„์€ ํƒ์ง€ ์˜ค๋ฅ˜์ž…๋‹ˆ๋‹ค.)

#์•„๋ž˜ shark_list๋Š” ์ ์ ˆํ•œ jpg ํŒŒ์ผ๋ช…์œผ๋กœ ๋ณ€๊ฒฝ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
shark_list = ['d92290f6c04dd83b.jpg', '3a37a09ec201cdeb.jpg', '32717894b5ce0052.jpg', 'a848df5dbed78a0f.jpg', '3283eafe11a847c3.jpg']
for image_name in shark_list:
    img = Image.open(os.path.join(IMAGE_DIR, image_name))
    detected_img = ballnfish_yolo.detect_image(img)
    plt.figure(figsize=(8, 8))
    plt.imshow(detected_img)
  • Object Detection ๊ฒฐ๊ณผ 

#์•„๋ž˜ shell_list๋Š” ์ ์ ˆํ•œ jpg ํŒŒ์ผ๋ช…์œผ๋กœ ๋ณ€๊ฒฝ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
shell_list=['5cc89bc28084e8e8.jpg',  '055e756883766e1f.jpg', '089354fc39f5d82d.jpg', '80eddfdcb3384458.jpg']
for image_name in shell_list:
    img = Image.open(os.path.join(IMAGE_DIR, image_name))
    detected_img = ballnfish_yolo.detect_image(img)
    plt.figure(figsize=(8, 8))
    plt.imshow(detected_img)
  • Object Detection ๊ฒฐ๊ณผ 

์˜์ƒ Object Detection์€ Part.2 ๊ธ€๋กœ ์ด์–ด์ง‘๋‹ˆ๋‹ค.