Final Ranking : 4th / 20teams
AP50:95 - FPS (Tesla V100) Paper: https://arxiv.org/abs/2011.08036
AP50:95 / AP50 - FPS (Tesla V100) Paper: https://arxiv.org/abs/2004.10934
fork : https://github.com/AlexeyAB/darknet
Paper YOLO v4: https://arxiv.org/abs/2004.10934
Paper Scaled YOLO v4: https://arxiv.org/abs/2011.08036 use to reproduce results: ScaledYOLOv4
์ด๋ฒ Teeth Object Detection & numbering Challenge๋ฅผ ์ฐธ์ฌํ๊ณ ๊ทธ ์ค ์ ๊ฐ ๋งก์ ๋ชจ๋ธ์ธ YOLOv4์ ๋ํด Challenge์ฉ์ผ๋ก ํ์ฉํ๋ ์ค๋ช ์ ๋ํด์ ์์ฑ์ ํ๋ คํฉ๋๋ค. ์์ ์์ block์ YOLOv4 github๊ณผ paper ๋งํฌ๋ฅผ ๋ฌ์๋์๊ณ , repo๋ darknet YOLOv4์์ fork๋ฅผ ๋ ์์์ ๋ฐํ๋๋ค.
Notion YOLOv4 ์ ๋ฆฌ๊ธ : https://www.notion.so/YOLOv4-Optimal-Speed-and-Accuracy-of-Object-Detection-e1e4178c0eac40f7a7e76a6768e5e256
์ฒ์ Object Detection๋ถ์ผ๋ก ์ฑ๋ฆฐ์ง๋ฅผ ์ฐธ๊ฐํ๋ฉด์ paper์ ์ ๋ฆฌ๋ blog๋ค์ ์ฝ์ผ๋ฉฐ YOLOv4์ ๋ํด ๊ณต๋ถํ์์ต๋๋ค. YOLOv4๋ฅผ Challenge์์ ํ์ฉํ๋ฉด์ Custom Dataset์ ํ์ต์ํค๋ ๋ฐฉ๋ฒ๋ค์ Google์ ์ ์ค๋ช ๋ ๋ธ๋ก๊ทธ๊ฐ ๋ง์ ๋ธ๋ก๊ทธ๋ฅผ ํ์ฉํ์์ต๋๋ค.
YOLOv4 custom dataset training tutorial : https://keyog.tistory.com/21
์ ๊ฐ Challenge์์ ์ฌ์ฉํ๋ Data๋ ์น๊ณผ Panorama data์์ผ๋ฉฐ training set์ ๋ํ annotation์ json์ผ๋ก ๊ฐ ๋ฐ์ดํฐ์ ๋ํด ํ์๋ ํํ์์ต๋๋ค.
์ฐ์ darknet github์์ Code๋ฅผ ๋๋ฌ HTTPS์ ๋ํ ๋งํฌ๋ฅผ ๋ณต์ฌํ์ฌ local๋ก ๋ค์ด๋ก๋ํฉ๋๋ค.
git clone https://github.com/AlexeyAB/darknet.git
[img1 ์๋ฆฌ]
git clone์ ํตํด repo๋ฅผ ๋ค์ด๋ฐ์๋ค๋ฉด ์ฒซ ๋ฒ์งธ๋ก ์งํํด์ผํ ๊ฒ์ config ์์
์ด๋ค.
cd cfg/
vim yolov4.cfg
Vim editor๊ฐ ์๋๋๋ผ๋ ๋ค๋ฅธ Text Editor๋ฅผ ์ฌ์ฉํด๋ ๋ฌธ์ ๊ฐ ์์ต๋๋ค. ํ์๋ vim editor๋ฅผ ํตํด yolov4.cfg
ํ์ผ์ ์์ ํ์์ต๋๋ค.
[img 02]
์ด๋ฏธ์ง์์ ๋ณผ ๋, ์์ ํด์ผํ ๋ถ๋ถ์ batch์ subdivision, width, height ๋ฑ์ ์์ ํ๊ณ max_batches, steps ๋ฑ์ ์์ ํ๋ฉด ๋๋ค.
- Batch : Batchsize๋ 8๋ก ์ง์ ํ์ฌ ์ฌ์ฉํ์๋๋ฐ, ํ์ต์ํค๋ GPU์ Memory์ ๋ฐ๋ผ ๋ง์ถ๋ฉด ๋ ๊ฒ ๊ฐ๋ค.
- Subdivision : ์ด ๋ถ๋ถ์ ๋ํด์๋ ์์ธํ ์ดํด๊ฐ ์๊ฐ๋๋ฐ, GPU memory๋ฅผ ๋ค๋ฃจ๋ ๊ฒ๊ณผ ๊ด๋ จ์ด ์์ด๋ณด์๋ค. ๋๋ถ๋ถ์ ์ ๋ฆฌ๋ ๋ธ๋ก๊ทธ์์ 16์ผ๋ก ์ค์ ํ์ฌ ์งํํ์๊ณ ์ ๋
subdivisions=16
์ผ๋ก ์งํํ์ ๋ ํฐ ๋ฌธ์ ๊ฐ ๋ฐ์ํ์ง ์์์ต๋๋ค. - Max_batches : max_batches๋ AlexeyAB github์์ ์งํํ๋ผ๊ณ ์ ์ด๋ ๋ด์ฉ ๊ทธ๋๋ก๋ฅผ ์ฌ์ฉํ์์ต๋๋ค. ์ฌ์ฉํ์๋ ๋ถ๊ป์ Object Detection์ ์งํํ๋ฉฐ Classification์ ์งํํ Class์ ๊ฐฏ์ * 2000 ์ ์ ์ด์ฃผ์๋ฉด ๋ฉ๋๋ค. ์ ๋ ์น์์ class๊ฐ ์ด 32๊ฐ์ด๊ธฐ ๋๋ฌธ์ 32 * 2000 = 64000์ผ๋ก ์งํํ์์ต๋๋ค.
- Steps : max_batches์ 80%์์น์ 90% ์์น๋ฅผ ์ ์ด์ฃผ๋ฉด ๋ฉ๋๋ค. ์ ์ ๊ฒฝ์ฐ 64000*0.8, 64000 * 0.9 ->
51200, 57600
์ผ๋ก ์ ์ด์ฃผ์์ต๋๋ค.
[net]
batch=8
subdivisions=16
# Training
#width=512
#height=512
width=512
height=512
channels=3
momentum=0.949
decay=0.0005
angle=0
saturation = 1.5
exposure = 1.5
hue=.1
learning_rate=0.00261
burn_in=1000
max_batches = 64000
policy=steps
steps=251200, 57600
scales=.1,.1
Mosaic=1 ์ด ๋ถ๋ถ์ ์๋ง ๋ ผ๋ฌธ์์ Mosaic Augmentation์ ํ์ฉํ์๋๋ฐ, training augmentation์ ์ฌ์ฉํ๋ ์ง ์ํ๋ ์ง์ ๋ํด ์ค์ ํ๋ ๋ถ๋ถ ๊ฐ์์ต๋๋ค.
์ด ๋ค์์ผ๋ก๋ ๊ทธ ๋ฐ ๋ถ๋ถ์ ์์ ํ ์ฐจ๋ก์ ๋๋ค. yolo๋ผ๊ณ ๊ฒ์ํ์ฌ classes์ yolo์์ filter ํฌ๊ธฐ๋ฅผ ์์ ํ๋ฉด๋ฉ๋๋ค.
vim editor์ ๊ฒฝ์ฐ, esc๋ฅผ ๋๋ฅธ ํ
/yolo
๋ผ๊ณ ๊ฒ์ํ์๋ฉด ๋ ๊ฒ ๊ฐ์ต๋๋ค.
classes๋ ์ฌ์ฉํ์๋ ๋ฐ์ดํฐ์ ์ class ๊ฐฏ์, filter์ ๊ฐฏ์๋ (classes + 5) * 3 ์ผ๋ก ๊ฒ์ฐํ์ฌ ์ ์ ๊ฒฝ์ฐ์๋ classes 32, filter ๊ฐฏ์๋ (32 + 5) * 3 = 111 ์ด์์ต๋๋ค.
[convolutional]
size=1
stride=1
pad=1
filters=111
activation=linear
[yolo]
mask = 0,1,2
anchors = 12, 16, 19, 36, 40, 28, 36, 75, 76, 55, 72, 146, 142, 110, 192, 243, 459, 401
classes=32
num=9
jitter=.3
ignore_thresh = .7
truth_thresh = 1
scale_x_y = 1.2
iou_thresh=0.213
cls_normalizer=1.0
iou_normalizer=0.07
iou_loss=ciou
nms_kind=greedynms
beta_nms=0.6
cfg์์ ์์ ๊ฐ์ด ์์ ํด์ผํ ๋ถ๋ถ์ ์ด 3๊ฐ! vim์ ํตํด์ /yolo๋ฅผ ์ฐพ์๋ค๋ฉด ์๋ฌธ์ n ์ ํตํด์ ๋ค์ yolo๋ก ๋์ด๊ฐ ์ ์์ต๋๋ค. ๋ชจ๋ ๋์ผํ๊ฒ ์์ ํด์ฃผ์ด์ผํฉ๋๋ค!!
์ด์ ๋ ๋ฐ์ดํฐ์ ์ ์ฐ๊ธฐ ์ฉ์ดํ๊ฒ ์ ๋ฆฌํ๋ ํ์ผ๋ค์ ๋ง๋ค๋๋ก ํ๊ฒ ์ต๋๋ค.
๋ง๋ค์ด์ผํ ํ์ผ์ ํฌ๊ฒ 3๊ฐ์ง์ ๋๋ค.
custom.txt
custom.names
custom.data
๋ฐ์ดํฐ๊ฐ ๋ค์ด์๋ ํด๋(.jpg, .png๋ฑ)์ ๊ฐ๊ฐ์ ์ด๋ฏธ์ง์ ๋ํด์ txtํ์ผ ๋ง๋ค๊ธฐ(annotation)
์ฒซ ๋ฒ์งธ๋ก custom.txt(์ฐธ๊ณ ํ ๋ธ๋ก๊ทธ๋ฅผ ๋ณผ ๋ train.txt๋ก ์ ์ฅํ์๋๋ฐ, ์ ๋ ์์๋ก ์ด๋ฆ์ ๋ณ๊ฒฝํ์์ต๋๋ค.)๋ฅผ ๋ง๋ค ๋์ ์์์ ๋๋ค.
vim custom.txt
/Users/data/img/img_01.png
/Users/data/img/img_02.png
/Users/data/img/img_03.png
/Users/data/img/img_04.png
/Users/data/img/img_05.png
train ๋ฐ์ดํฐ๋ก ์ฌ์ฉํ ๊ฒฝ๋ก์ ํ์ผ์ด๋ฆ์ ๋ชจ๋ ์ ๋๋ฐ, ์๋๊ฒฝ๋ก๋ณด๋ค๋ ์ ๋๊ฒฝ๋ก๋ก ์ ๋ ๊ฒ์ ์ถ์ฒ๋๋ฆฝ๋๋ค.
๋ ๋ฒ์งธ๋ก๋ custom.data ํ์ผ์ ์์ฑํ ์ฐจ๋ก์ ๋๋ค. YOLO ํ๋ จ์ ์งํํ๋ฉด์ ์ฐธ๊ณ ํ๋ ํ์ผ์ด๋ผ๊ณ ์๊ฐํฉ๋๋ค.
classes=32
train = "txtํ์ผ์ด ์๋ ๊ฒฝ๋ก"/custom.txt
valid = "validation ํ์ผ์ด ๋ฐ๋ก ์์ ๊ฒฝ์ฐ custom_validationํ์ผ์ ๋ง๋ค์ด custom.txt์ ๊ฐ์ ๊ฒฝ๋ก์ ๋ง๋ค์ด ๋์๋ฉด ๋ฉ๋๋ค."
names = "txtํ์ผ์ด ์๋ ๊ฒฝ๋ก"/custom.names #์๋์ custom.names๋ฅผ ๋ง๋๋ ๋ฐฉ๋ฒ๋ ์ ์ด๋๊ฒ ์ต๋๋ค.
backup = backup/ #ํ๋ จ์ ์งํํ๋ฉด์ weight ํ์ผ์ด iteration ๋จ์๋ก ๋์ค๊ฒ ๋ฉ๋๋ค. ๊ทธ weight ํ์ผ์ด ์ ์ฅ๋๋ ๊ฒฝ๋ก์
๋๋ค.
์ธ ๋ฒ์งธ๋ก๋ custom.names ํ์ผ์ ์์ฑํ ์ฐจ๋ก์
๋๋ค. ์ ์ ๊ฒฝ์ฐ์๋ ์น์ ๋ฒํธ๊ฐ 1118, 2128, 3138, 4148 ์ด์์ต๋๋ค. ์ด๋ฅผ ์์๋๋ก ์ ์ด์ฃผ๋ฉด ๋ฉ๋๋ค.
11
12
13
...
44
45
46
47
48
๋ฐ์ดํฐ๊ฐ ๋ค์ด์๋ ํด๋(.jpg, .png๋ฑ)์ ๊ฐ๊ฐ์ ์ด๋ฏธ์ง์ ๋ํด์ txtํ์ผ ๋ง๋ค๊ธฐ(annotation)
๋ง์ง๋ง์ผ๋ก๋ custom dataset์ ๋ํด์ ๊ฐ์ง๊ณ ์๋ annotation ํ์ผ์ ๊ฐ๊ฐ์ ์ด๋ฏธ์ง์ ๋ํด์ .txtํ์ผ๋ก ๋ง๋ค์ด์ฃผ์ด์ผํฉ๋๋ค. (๊ผญ ๋ฐ์ดํฐ(.png)๊ฐ ๋ค์ด๊ฐ์๋ ํด๋์์ ์ด๋ฆ๊ณผ ๋งค์นญํด์ ๋ฃ์ด์ฃผ์ด์ผํฉ๋๋ค!)
์๋ฅผ ๋ค์ด
(base) โ data (master) โ tree
.
โโโ img_1.png
โโโ img_1.txt
โโโ img_2.png
โโโ img_2.txt
โโโ img_3.png
โโโ img_3.txt
โโโ img_4.png
โโโ img_4.txt
โโโ img_5.png
โโโ img_5.txt
0 directories, 10 files
์ด๋ฐ์์ผ๋ก ๋ฐ์ดํฐ๊ฐ ๋ค์ด์๋ ํด๋(์ ๋ data๋ผ๋ ํด๋์์ ์๋ค๊ณ ๊ฐ์ ํ์ ๋)์ data ์ด๋ฆ๊ณผ ๋์ผํ๊ฒ .txtํ์ผ์ ๋ง๋ค์ด์ฃผ์ด์ผ ํฉ๋๋ค.
.txtํ์ผ ์์๋ (0์์ ์์ / ๋ชจ๋ธ์ด ๋ฝ๋ ์์ํ์ class๋ก ๋ง์ถฐ์ผํฉ๋๋ค.), ์ด๋ ๊ฒ ์ด 5๊ฐ๋ฅผ ์ ์ด์ฃผ์ด์ผ ํ๋๋ฐ, ๋ ์ด๋ฏธ์ง์ .png์ shape ๋ด์์์ ์๋์ขํ์ ๋๋ค. (0 ~ 1)
# img_1.txt ๋ด๋ถ
0 0.716797 0.395833 0.216406 0.147222
1 0.687109 0.379167 0.255469 0.158333
2 0.420312 0.395833 0.140625 0.166667
...
ํด๋น ์ฝ๋๋ python์ ํตํด์ ๊ตฌํํ์์๋๋ฐ, ์๋ฒ๊ฐ ๋ซํ๋ ๋ฐ๋์ ๊ธ์ด์ค์ง ๋ชปํด ์์ฝ์ต๋๋ค. Challenge์์์ annotation์ ๋ก ๊ตฌํ ๋ผ ์์ด์ ๊ฐ๋จํ๊ฒ ์๊ณ ๋ฆฌ์ฆ์ผ๋ก ์ ๋ฆฌ๋ฅผ ํ๋ค๋ฉด
from PIL import Image
import numpy as np
import os
for img in sorted(os.listdir("data๊ฒฝ๋ก")):
img_shp = np.array(Image.open(img)).shape[:2]
#img_shp[0]๋ height์ ์ฐ๊ด๋จ
#img_shp[1]๋ width์ ์ฐ๊ด๋จ
#ํ
์คํธ๋ก ์ ์ฅํ ๋ xmin, ymin, xmax, ymax ์์ ๋๋ต
#center x = xmin+xmax/2
#center y = ymin+ymax/2
#์๋์ขํ width (xmax - xmin) / img_shp[1]
#์๋์ขํ height (ymax - ymin) / img_shp[0]
์ด๋ฐ์์ผ๋ก txtํ์ผ์ ์ ์ฅํ๋๋ก ์ฝ๋ ์์ฑํด์ฃผ๋ฉด ๋ฉ๋๋ค. yolo๋ ์๋์ขํ๋ก ์งํ๋๋ ์ ๊ณผ xmin, xmax, ymin, ymax ํ์์ annotation์ ์ฌ์ฉํ๋ ๊ฒ์ด ์๋์ ์ฃผ์ํด์ผํฉ๋๋ค.
์ด์ ์ผ๋ง ๋จ์ง ์์์ต๋๋ค. c์ธ์ด๋ก ์์ฑ ๋ผ ์๋ ๋ชจ๋ธ์ compileํด์ฃผ์ด training์ ์งํํ๋ฉด ๋ฉ๋๋ค.
Darknet ์์ ๊ฒฝ๋ก์์
vim Makefile
Makefile์ ์์ ํฉ๋๋ค. GPU ์ฌ์ฉ ์ ๋ฌด, CUDNN ์ฌ์ฉ์ ๋ฌด, opencv ์ฌ์ฉ์ ๋ฌด ๋ฑ์ ์ ์ด์ฃผ๋ฉด ๋ฉ๋๋ค.
Makefile์ ์์ ํ ํ์๋
make
make๋ฅผ ํ์ดํํ์ฌ ์ปดํ์ผ์ ์งํํฉ๋๋ค.
์ด์ training์ ์งํํ๋ฉด ๋๋๋ฐ
./darknet detector train custom.data cfg/yolov4.cfg
ํด๋น ๋ช ๋ น์ด๋ก Training์ ์งํํ๋ฉด ๋ฉ๋๋ค. Pretrain weight๋ฅผ ์ฌ์ฉํ๊ณ ์ถ์ ๊ฒฝ์ฐ drive.google.com/open?id=1JKF-bdIklxOOVy-2Cr5qdvjgGpmGfcbp
๋งํฌ์์ yolov4.conv.137 ํ์ผ์ ๋ค์ด๋ก๋ ๋ฐ๊ณ
./darknet detector train custom.data cfg/yolov4.cfg yolov4.conv.137
์ด๋ ๊ฒ ํ์ต์ ์งํํด์ฃผ๋ฉด ๋ฉ๋๋ค.
Challenge์ ์ฐธ์ฌํ ๊ฒฝ์ฐ, Testset์ด ์ฃผ์ด์ง ๊ฒ์ ๋๋ค. testset์ ๋ํด์ inference๋ฅผ ์์ฑํด์ผํฉ๋๋ค.
./darknet detector test data/test.data "test์ ๋ํ cfg".cfg "ํ์ต์ ๋ง์น weight".weights -dont_show < "testset์ด ์๋ ์ด๋ฏธ์ง๋ค์ ์ ๋ฆฌ๋ .txtํ์ผ custom.txt์ ๋์ผํ ์์" > result.txt
inference๋ฅผ ๋ง์น ํ Challenge์์ ์ ๊ณตํ๋ submission ์์์ผ๋ก ๋ฐ๊พธ์ด์ ์ ์ถ์ ํ๋ฉด ๋ฉ๋๋ค. ์ ์ถ์์์ ๋ชจ๋ ๋ค๋ฅด๊ธฐ ๋๋ฌธ์ ์ฐธ๊ณ ์ฉ์ผ๋ก ์ฌ์ฉํ์๋ฉด ๋ ๊ฒ ๊ฐ์ต๋๋ค.
์ฐธ๊ณ ๋ก result.txt ์ output ๋ํ ์ด๋ฏ๋ก Challenge submission์์์ด ์ผ ๊ฒฝ์ฐ ์ถ๊ฐ์ ์ผ๋ก ๋ณํ์ ์งํํด์ฃผ์ด์ผํฉ๋๋ค.