μ΄μ ν¬μ€ν μμ μ΄λ―Έμ§ λΌλ²¨λ§ μμ μ μλ£ νλ€λ©΄
λΌλ²¨λ§ λ λ°μ΄ν°λ₯Ό YOLO νμμΌλ‘ μ ν ν΄μ£Όλλ‘ νκ² μ΅λλ€.
γ λ°μ΄ν° μ νμ λ³ν γ
νμ¬ CVATμ ν΅ν΄ λ€μ΄λ°μ λ°μ΄ν°λ COCOνμμ json νμΌμ λλ€.
μ΄λ₯Ό Yolov5μμ μ¬μ©νκΈ° μν΄ convert2Yoloλ₯Ό νμ©νλλ‘ νκ² μ΅λλ€.
covert2Yolo ν¨ν€μ§μ yolov5μ κ²½μ° μλμ git νμ΄μ§μμ
zip νμμ ν΅ν΄ λ€μ΄λ°μλ λκ³
μ½μ νΉμ ν°λ―Έλμ ν΅ν΄ λ€μ΄λ‘λ λ°μ μλ μμ΅λλ€.
[.zip νμμΌλ‘ μ§μ λ€μ΄]
GitHub - ultralytics/yolov5: YOLOv5 π in PyTorch > ONNX > CoreML > TFLite
YOLOv5 π in PyTorch > ONNX > CoreML > TFLite. Contribute to ultralytics/yolov5 development by creating an account on GitHub.
github.com
convert2Yolo κΉνλΈ νμ΄μ§
GitHub - ssaru/convert2Yolo: This project purpose is convert voc annotation xml file to yolo-darknet training file format
This project purpose is convert voc annotation xml file to yolo-darknet training file format - GitHub - ssaru/convert2Yolo: This project purpose is convert voc annotation xml file to yolo-darknet t...
github.com
γμ½μ νΉμ ν°λ―Έλμ ν΅ν git clone μμ±γ
## git clone ν μμΉμμ μν [convert2Yolo]
git clone https://github.com/ssaru/convert2Yolo.git
cd convert2Yolo
## yolov5 μνμ μν νλ¬κ·ΈμΈ μ€μΉ
# pip install -r requirements.txt
## git clone ν μμΉμμ μν [yolov5]
git clone https://github.com/ultralytics/yolov5.git
cd yolov5
## yolov5 μνμ μν νλ¬κ·ΈμΈ μ€μΉ
# pip install -r requirements.txt
convert2Yolo, yolov5 ν¨ν€μ§λ₯Ό νλ‘μ νΈ ν΄λ νμμ clone νκ³
μλμ ν΄λ κ΅¬μ‘°λ‘ νλ‘μ νΈλ₯Ό κ΄λ¦¬ν΄ μ€λλ€.
# νλ‘μ νΈ
# βββ yolov5
# βββ convert2Yolo
# βββ ship (λ°μ΄ν° μ
μ λ΄μ ν¨ν€μ§)
# βββ class.names
# βββ labels.json(CVATμ ν΅ν COCO νμμ μ΄λ―Έμ§ μ΄λ Έν μ΄μ νμΌ)
# βββ data
# βββ images (CVATμ ν΅ν΄ λΌλ²¨λ§ν λ μ¬μ©λμλ μ΄λ―Έμ§ νμΌμ λ΄λ ν΄λ)
# βββ labels (convert2Yoloλ₯Ό ν΅ν YOLO μ΄λ
Έν
μ΄μ
νμΌμ λ΄μ ν΄λ)
μ΄ λ class.names νμΌμ κ²½μ° λ°μ΄ν°μ μ ν΄λμ€λ€λ₯Ό ꡬλΆνλ νμΌμ΄λ―λ‘
ν΄λΉνλ ν΄λμ€λͺ λ€μ μμ±ν΄μ€λλ€.
## class.names
# CVATμ ν΅ν΄ λΆλ₯ν labelλͺ
μ ν μ€μ© κΈ°μ
ship
μ΄μ νλμ json νμΌ μ΄λ―Έμ§μ λ§λ YOLO μ΄λ Έν μ΄μ νμΌ(.txt)λ‘ λ³νμμΌμΌ ν©λλ€.
# convert2Yolo ν΄λλ‘ μ΄λ
cd convert2Yolo
# labels.json νμΌ txt λ³ν
'''
python(python3, pip..) install example.py \
--datasets 'λ³ν labels ν¬λ§·' \
--img_path 'μ΄λ―Έμ§ κ²½λ‘' \
--img_type 'μ΄λ―Έμ§ νμ
' \
--label 'label.jsonνμΌ κ²½λ‘' \
--convert_output_path 'λ³ν txt νμΌ μ μ₯ κ²½λ‘' \
--manifest_path 'ν΄λΉμ¬ν μμΌλ μ΅μ
μ μΈ λΆκ°ν κ²½μ° κΈ°λ³Έκ° ./λ‘ μμ±' \
--cls_list_file 'class.names νμΌ κ²½λ‘' \
'''
# μ€μ μ€ν μ½λ
python example.py \
--dataset COCO \
--label ../ship/labels.json \
--convert_output_path ../ship/data/labels \
--cls_list_file ../ship/class.names \
--img_path ../ship/data/images \
--img_type ".jpg" \
--manifest_path ./
ν΄λΉ λͺ λ Ήμ΄λ₯Ό ν΅ν΄ completeκ° λ¨λ©΄ λ³νμ΄ μ±κ³΅μ μΌλ‘ μλ£λ κ²μ λλ€.
convert_output_pathλ‘ μ§μ ν
../ship/data/labels ν΄λμ λ³νν txt νμΌμ΄ μ‘΄μ¬νλμ§ νμΈν΄λ³΄λλ‘ ν©λλ€.
μ΄λ―Έμ§μ κ°―μμ λμΌν κ°―μ, μ΄λ¦μ .txtκ° μμ±λμμ΅λλ€.
# βββ data
# βββ images
# βββ labels
# βββ ship1.txt
# βββ ship2.txt
# βββ ship3.txt...
μ΄μ yaml νμΌμ μμ±ν΄μ£Όλλ‘ ν©λλ€.
yaml νμΌμ YOLOμ λ°μ΄ν° μμΉ, ν΄λμ€ κ°μ λ±μ μ 보λ₯Ό μ λ¬νλ νμΌμ λλ€.
## custom.yaml
'''
path: κΈ°λ³Έκ²½λ‘ μ§μ
train: training κ²½λ‘ μ§μ
test : test κ²½λ‘ μ§μ
val: val κ²½λ‘ μ§μ
nc: ν΄λμ€ κ°―μ μ§μ
names = ν΄λμ€λͺ
μ§μ
'''
# μ€μ μμ± μ½λ
path: C:/Users/νλ‘μ νΈλͺ
/ship/data
train: images/train
test : images/test
val: images/val
nc: 1
names: ['ship']
μ΄μ λͺ¨λΈμ νλ ¨ν νκ²½μ΄ λμμΌλ λ°μ΄ν° μ μ
train, val, testλ‘ λΆλ₯ν΄μ£Όλλ‘ ν©λλ€.
λ³΄ν΅ λ°μ΄ν°μ μ Train/ValidationμΌλ‘ λλ λλ 70/30 λΉμ¨λ‘,
Train/Validation/Testλ‘ λλ κ²½μ°μλ 70/20/10 λΉμ¨λ‘ λλλ€κ³ ν©λλ€.
νμ¬ μ κ° CVATμ ν΅ν΄ λΌλ²¨λ§ν μ΄λ―Έμ§ νμΌμ 100κ°μ΄κ³
μ΄λ₯Ό ν΅ν΄ exportν labels.json νμΌμ convert2Yoloλ₯Ό μ¬μ©νμ¬ λ³νλ
txtνμΌλν λμΌνκ² 100κ°μ΄λ―λ‘
μ΄μ ν΄λΉ νμΌλ€μ 70/20/10μΌλ‘ λλμ΄ μ£Όμ΄μΌ νλλ°
μ΄μ μ νμ΄μ¬ ν¬λ‘€λ§μ ν΅ν΄ λ€μ΄λ°μ μ΄λ―Έμ§μ λͺ μΉμ΄
μ‘°κΈ μμ΄νκΈ° λλ¬Έμ ν΄λΉ μ΄λ―Έμ§ νμΌκ³Ό txtνμΌ λͺ μΉμ
λΆλ₯νμ¬ λ€μ κ° ν΄λμ λ£μ΄μ£Όκ² μ΅λλ€.
μ΄λ₯Ό μν΄ images ν΄λμ labels ν΄λ νμμ κ°κ° ν΄λλ€μ μμ±ν΄μ€λλ€.
# βββ ship
# βββ data
# βββ images
# βββ test (ν μ€νΈλ₯Ό μνν 20μ₯μ μ΄λ―Έμ§λ₯Ό λ΄λ ν΄λ)
# βββ train (trainμ μνν 70μ₯μ μ΄λ―Έμ§λ₯Ό λ΄λ ν΄λ)
# βββ val (valμ μνν 10μ₯μ μ΄λ―Έμ§λ₯Ό λ΄λ ν΄λ)
# βββ labels
# βββ test (ν μ€νΈλ₯Ό μνν 20μ₯μ ν μ€νΈλ₯Ό λ΄λ ν΄λ)
# βββ train (trainμ μνν 70μ₯μ ν μ€νΈλ₯Ό λ΄λ ν΄λ)
# βββ val (valμ μνν 10μ₯μ ν μ€νΈλ₯Ό λ΄λ ν΄λ)
νμ¬ μ€μ μ΄λ―Έμ§μ μ΄λ Έν μ΄μ (txt) νμΌλ€μ κ°κ°
/images νμ,
/labels νμμ κ°κ° 100κ°μ© μ‘΄μ¬νλ μνμ λλ€.
μ΄λ₯Ό νμ΄μ¬ μ½λλ‘ μμ±λ convert_file.py νμΌμ μμ±νμ¬
μ΄λ―Έμ§ νμΌκ³Ό ν μ€νΈ νμΌλ€μ λΆλ₯ν΄μ£Όκ² μ΅λλ€.
ν΄λΉ νμΌμμ FILE_PATHμ FILE_EX λΆλΆλ§ νλ²μ© λ³κ²½ν΄ μ€ννλ©΄ λ©λλ€.
γμ΄λ―Έμ§ λ° μ΄λ Έν μ΄μ νμΌ λΆλ₯γ
## /ship/data/convert_file.py
import os
FILE_PATH = "./labels/" # νμ¬ μμ ν ν΄λ κ²½λ‘: labels, images
FILE_EX = ".txt" # νμΌ νμ
μμ : images, txt
TRAIN_FILE_PATH = FILE_PATH + "train"
VAL_FILE_PATH = FILE_PATH + "val"
TEST_FILE_PATH = FILE_PATH + "test"
file_list = [file for file in os.listdir(FILE_PATH) if file.endswith(FILE_EX)]
train_cnt, val_cnt, test_cnt = 1, 1, 1
def convert_img_file(o_file_name, c_file_name, c_file_path):
src = os.path.join(FILE_PATH, o_file_name)
c_file_name = c_file_name + FILE_EX
dst = os.path.join(c_file_path, c_file_name)
os.rename(src, dst)
for i, file_name in enumerate(file_list):
if i < 70:
convert_img_file(file_name, f"train_{train_cnt}", TRAIN_FILE_PATH)
train_cnt += 1
elif i < 90:
convert_img_file(file_name, f"val_{val_cnt}", VAL_FILE_PATH)
val_cnt += 1
elif i < 100:
convert_img_file(file_name, f"test_{test_cnt}", TEST_FILE_PATH)
test_cnt += 1
ν΄λΉ μ½λλ₯Ό ν΅ν΄ νμΌλ€μ λΆλ₯κ° μ μμ μΌλ‘ μλ£λμλ€λ©΄
μ΄μ ν΄λΉ λ°μ΄ν°μ μ YOLOv5 λͺ¨λΈμ ν΅ν΄ νλ ¨μν€λλ‘ νκ² μ΅λλ€.
γ λ°μ΄ν° μ μ ν΅ν λͺ¨λΈ νμ΅ γ
yolov5μμ μ 곡νλ λͺ¨λΈμ 4κ°μ§μ΄λ©° μ€λ₯Έμͺ½μ λͺ¨λΈμΌμλ‘
μ νλκ° μμΉνμ§λ§ νμ΅ μκ°μ΄ μ€λ걸리λ λͺ¨λΈμ λλ€.
λ³ΈμΈμ νλ‘μ νΈμ λ§μΆ°μ μλ§κ² μ¬μ©νλ©΄ λ κ² κ°μ΅λλ€.
μ μ κ²½μ° YOLOv5m λͺ¨λΈμ μ¬μ©νμΌλ©°,
μν¬ν¬ μμ λ°°μΉλ λ°λ‘ μ‘°μ νμ§ μμμ΅λλ€.
(μν¬ν¬ μ λ―Έ μ§μ μ κΈ°λ³Έκ° : 100)
γλͺ¨λΈ Trainγ
## yolov5 κ²½λ‘ μ΄λ
cd ../yolov5
## λͺ¨λΈ Train μν
'''
python train.py \
--img 'μ΄λ―Έμ§ μ¬μ΄μ¦' \
--batch 'λ°°μΉ μ¬μ΄μ¦' \
--data 'custom.yaml νμΌ κ²½λ‘' \
--cfg 'μ¬μ©ν λͺ¨λΈμ yaml νμΌ κ²½λ‘' \
--weights 'νμ΅μ μ¬μ©ν λͺ¨λΈ' \
--name 'νμ΅λ μ 보λ₯Ό runs ν΄λ μμ μ μ₯ν μ΄λ¦'
--project 'wandbμ μ μ₯ν νλ‘μ νΈ λͺ
'
'''
## μ€μ μ€ν μ½λ
python train.py \
--data ../ship/custom.yaml \
--weights yolov5m.pt
Train νμ΅ κ²°κ³Όλ yolov5/runs/train κ²½λ‘μ μ΅μ΄μ
/expλΌλ ν΄λλ‘ μ μ₯λκ² λ©λλ€.
νμ΅μ λ°λ³΅νλ©΄ /train νμ κ²½λ‘μ exp1, exp2, exp3...
ννλ‘ ν΄λκ° μμ±λλ©° νμ΅ κ²°κ³Όκ° κΈ°λ‘λ©λλ€.
μ΄ λ νμ΅ κ²°κ³Ό ν΄λμμ
val_batch_labels νμΌμ κ° μ΄λ―Έμ§ λ³ μ λ΅ λ°μ΄λ©λ°μ€λ₯Ό μλ―Ένκ³
val_batch_pred.jpg νμΌμ μμΈ‘λ λ°μ΄λ©λ°μ€κ°μ 보μ¬μ€λλ€.
μ΄λ₯Ό ν΅ν΄ μμΈ‘ μ νλλ₯Ό λλ΅μ μΌλ‘ νλ³ κ°λ₯ν©λλ€.
κΈ°λ³Έμ μΌλ‘ YOLOv5 λͺ¨λΈμ ν΅ν Trainμ μ§νν κ²½μ°
Valλ κ°μ΄ μ§νλμ΄ νμ΅ κ²°κ³Όκ° κ°μ΄ μ μ₯λ©λλ€.
λ§μ½ Val μ§νμ νμΈνκ³ μΆλ€λ©΄
μλμ ν΄λΉ μ½λλ₯Ό ν΅ν΄ νμΈ κ°λ₯ν©λλ€.
μ΄ ν Inference, Val, Test νμ΅ λͺ¨λ Trainμ ν΅ν΄
νμ΅λ λͺ¨λΈ μ€ κ°μ₯ μ’μ λͺ¨λΈμΈ /exp/weights/best.ptλ₯Ό μ΄μ©ν©λλ€.
γ λͺ¨λΈ Val γ
## yolov5 ν΄λ κ²½λ‘μμ μ§ν
# λͺ¨λΈ Val μν
python val.py \
--data ../ship/custom.yaml \
--weights 'runs/train/exp/weights/best.pt' \
--save-txt
--save-txt νλΌλ―Έν°λ₯Ό ν΅ν΄ bounding box λ°μ΄ν°λ₯Ό
ν μ€νΈ νμΌλ‘ νμΈ κ°λ₯ν©λλ€.
λν Testμ κ²½μ°
val.py μ€ν νλΌλ―Έν°λ‘ --task "test"λ₯Ό μ λ¬ν κ²½μ° μνν©λλ€.
γ λͺ¨λΈ Test γ
## yolov5 ν΄λ κ²½λ‘μμ μ§ν
# λͺ¨λΈ Test μν
python val.py \
--task "test" \
--data ../ship/custom.yaml \
--weights 'runs/train/exp/weights/best.pt' \
--save-txt
μ΄μ νμ΅ λͺ¨λΈκ³Ό νλ ¨ λ°μ΄ν°λ₯Ό ν΅ν΄
ν μ€νΈ λ°μ΄ν°λ₯Ό λ£μ΄
Inferenceλ₯Ό μ§νν΄ λ³΄κ² μ΅λλ€.
γν μ€νΈ λ°μ΄ν° Inferenceγ
## yolov5 ν΄λ κ²½λ‘μμ μ§ν
'''
python detect.py \
--source ν
μ€νΈν νμΌ κ²½λ‘ \
--weights 'runs/train/exp/weights/best.pt'
'''
# μ€μ μν μ½λ
python detect.py \
--source './test_img.jgp' \
--weights 'runs/train/exp/weights/best.pt'
ν μ€νΈ μ΄λ―Έμ§ νλμ μ νλΈ λ§ν¬λ₯Ό ν΅ν΄ μ§νν΄λ³΄μμ΅λλ€.
κΈμλ₯Ό μ λ°μΌλ‘ μΈμνλ λ± μμ£Ό λͺ
ννκ²λ μλμ§λ§
μΌμ λΆλΆ κΈ°λ₯νκ³ μμμ νμΈν μ μμ΅λλ€.
μ°Έκ³
https://magicode.tistory.com/55#article-1--1--%EC%9D%B4%EB%AF%B8%EC%A7%80-%EC%A4%80%EB%B9%84
https://developnote-blog.tistory.com/161
https://minmiin.tistory.com/16