🚀Project🚀/Navigation with detecting person

[Project 1] - (1) YOLOv8 성능 확인해 보기

고집호랑이 2023. 4. 25. 12:50

최근에 프로젝트를 진행하다가 포스팅이 많이 밀렸네요. 제가 이번에 맡은 프로젝트는

 

로봇이 Nav2를 통해 목적지까지 주행하다가 카메라로 사람이 인식되면 경로를 멈추고 사람이 사라지면 다시 주행하는 프로젝트

였습니다. 현재 이 부분을 성공적으로 완성시켰고 이후 필요에 따라 계속 발전시켜 나갈 예정입니다. 

 

이 과정에서 YOLOv8부터 Behavior Tree, Groot 등등 여러 가지가 사용되었는데, 이것들에 대해서 공부하며 정리했던 자세한 내용들은 Object Detection과 Nav2 카테고리에 차차 포스팅하도록 하고 이곳에서는 Project가 진행되었던 과정에 대해서 포스팅하려고 합니다.


Object Detection 모델 선택

먼저 사람을 detection하기 위한 모델부터 선택해야 합니다. 이후에 사람뿐만 아니라 다른 객체들도 detection 해야 할 필요도 생길 가능성이 크기 때문에 여러 객체를 detection 하는데 높은 성능(mAP)을 보여줘야 하며 실시간으로 들어오는 비디오 이미지에서 사람을 detect 해야 하므로 예측 속도 또한 빨라야 합니다.

 

이러한 조건에 가장 알맞은 모델로, 가장 최근에 나온 YOLO 버전이자 2023년 1월 Ultralytics에서 개발된 YOLOv8을 사용하기로 결정했습니다. 

 

YOLOv8의 mAP
YOLOv8의 mAP
YOLOv8의 예측 속도

 

위 그림과 같이 YOLOv8의 속도가 아주 빠르다는 것과 성능 또한 다른 모델에 비해 우수한 것을 확인할 수 있습니다. 

 

그렇지만 YOLOv8은 가장 최근에 나온 모델인지라 YOLOv8이 사용된 선례도 많이 없을뿐더러 공식적인 논문도 아직 나오지 않았기 때문에 학습은 잘되는지, 예측은 잘되는지에 대해서는 한 번 확인해 볼 필요가 있습니다.

 

YOLOv8 성능 확인해 보기

새로운 dataset으로 직접 학습까지 시켜볼 것이기 때문에 편의를 위해 gpu 사용이 가능한 Colab을 사용하였습니다.

 

Ultralytics Yolov8 설치

!pip install ultralytics

먼저 YOLOv8을 사용하기 위해서는 ultralytics 패키지를 pip install 해야 합니다. YOLOv8을 사용하기 위해 필요한 다른 패키지들도 자동적으로 설치됩니다.

 

이미지 Detection 수행해보기

import cv2
from ultralytics import YOLO

# Load a model
model = YOLO("yolov8n.pt")  # COCO dataset으로 pretrained된 model을 불러옴

# Use the model
results = model.predict("https://ultralytics.com/images/bus.jpg")  # ultralytics 패키지 내에 test용으로 이미 존재해 있는 버스 이미지를 이용해 object detection 수행

 

먼저 cv2와 ultralytics를 import해주고, COCO dataset으로 pretrained된 YOLOv8 model을 불러옵니다. ultralytics 패키지는 크기에 따라서 5개의 pretrained된 모델을 제공해주는데(n, s, m, l, x), 이번에 사용한 것은 가장 크기가 작은 "yolov8n.pt" 입니다.

 

이제 ultralytics 패키지 내에 test용으로 존재하는 버스 이미지에서 object detection을 수행하고 결과를 살펴보겠습니다.

 

# print(results)

print(results[0])

print()

print(results[0].boxes) # 좌상단 좌표, 우하단 좌표, confidence score, class id

 

detect 결과를 저장한 results를 출력해보면 아래와 같이 list 형태 안에 class 종류들, 원본 이미지의 array 값들이 있는 것을 확인할 수 있습니다. 

 

results 결과
print(results) 출력 결과

 

detect한 object의 bounding box 좌표, confidence score, class id는 results[0].boxes로 접근해야 정보를 확인할 수 있습니다. 아래는 results[0].boxes의 출력 결과입니다.

 

print(results[0].boxes) 출력 결과

 

박스 표시한 것처럼 순서대로 detect된 object들의 좌상단 좌표, 우하단 좌표, confidence score, class id가 list 형태로 저장되어

있습니다.

 

# import matplotlib.pyplot as plt
from google.colab.patches import cv2_imshow # google의 자체 개발 라이브러리에서 cv2_imshow를 import

res_plotted = results[0].plot() # plot() 함수를 이용해서 이미지 내에 bounding box나 mask 등의 result 결과를 그릴 수 O
# print(res_plotted)

# plt.figure(figsize=(12, 12))
# plt.imshow(cv2.cvtColor(res_plotted, cv2.COLOR_BGR2RGB)) 
# plt.show()

cv2_imshow(res_plotted)

 

이제 detection 수행 결과를 이미지로 보려고 합니다. plot() 함수를 써주면 이전에 봤던 bounding box나 mask 정보를 원본 이미지에 표시를 해주기 때문에 이 함수를 사용하고 opencv의 imshow 함수를 사용하면 detection 결과를 확인할 수 있습니다.

 

이때 Colab 환경에서는 cv2.imshow()가 비활성화 되어있기 때문에 google이 자체 개발한 라이브러리에서 cv2_imshow를 import 해서 사용하던가 matplotlib.pyplot을 사용해주면 됩니다.

 
detect 결과

 

사람, 버스, 신호등 모두 잘 detect된 것을 확인할 수 있습니다. 

 

!mkdir /content/data
!wget -O /content/data/street01.jpg https://raw.githubusercontent.com/goodhsm2000/DL-YOLOv8_ex/main/street.jpg
results2 = model("/content/data/street01.jpg", conf = 0.5, save = True, line_thickness = 1)
cv2_imshow(results2[0].plot())

 

이후 새로운 이미지를 직접 다운로드해 detect 해봤는데, 과정은 이전과 동일합니다.(성능 시험에 사용한 data는 github에 업로드 함)

 

다만 이번에는 confidence score threshold를 지정할 수 있는 conf 인자와 결과를 저장할 지 여부를 정하는 save 인자 그리고 bounding box 선의 굵기를 조절할 수 있는 line_thickness 인자도 함께 사용했습니다.

 

detect 결과
detect 결과

 

사용할 수 있는 더 다양한 인자들은 아래 링크에서 확인할 수 있습니다.

 

https://docs.ultralytics.com/modes/predict/

 

Predict - Ultralytics YOLOv8 Docs

Predict YOLOv8 predict mode can generate predictions for various tasks, returning either a list of Results objects or a memory-efficient generator of Results objects when using the streaming mode. Enable streaming mode by passing stream=True in the predict

docs.ultralytics.com

 

fish image dataset으로 학습시켜 테스트해보기

COCO dataset으로 pretrained된 모델은 이미 존재하기 때문에 이제 새로운 dataset을 이용하여 YOLOv8 모델을 학습시켜보고 잘 학습됐는지 확인해보려고 합니다.

 

학습 시간을 줄이기 위해서 class 종류와 이미지 개수가 적당한 dataset을 찾다가 roboflow에 존재하는 여러 물고기 종류에 대한 image dataset을 선택했습니다.(아래 링크) 

 

https://universe.roboflow.com/roboflow-gw7yv/fish-yzfml/dataset/44

 

Fish Object Detection Dataset (v44, 2023-02-21 1:58pm) by Jacob Solawetz

680 open source fish images and annotations in multiple formats for training computer vision models. Fish (v44, 2023-02-21 1:58pm), created by Jacob Solawetz

universe.roboflow.com

 

# Google Drive 접근을 위한 Mount 적용. 
import os, sys 
from google.colab import drive 

drive.mount('/content/gdrive')

# soft link로 Google Drive Directory 연결. 
!ln -s /content/gdrive/My\ Drive/ /mydrive
!ls /mydrive

!mkdir "/mydrive/ultra_workdir"

 

Colab에서는 연결이 끊기면 다운받거나 저장한 파일이 모두 사라지기 때문에 학습 결과를 제 google drive에 저장하기 위해서 먼저 mount를 적용하고 goolge drive와 연결시켜줍니다.

 

이후 제 google drive에 ultra_workdir이라는 새 directory를 만들고 이곳에 train 결과를 저장할 예정입니다.

 

!wget -O /content/data/fishdata.zip https://raw.githubusercontent.com/goodhsm2000/DL-YOLOv8_ex/main/Fish.v44i.yolov8.zip
!cd /content/data; unzip fishdata.zip

 

fish image dataset을 다운받아 압축해제 시켜주고,

 

model = YOLO("yolov8n.pt")

model.train(data = "/content/data/data.yaml", epochs = 15, imgsz = 640, project = "/content/gdrive/MyDrive/ultra_workdir", name= "fish", exist_ok = True)

# !yolo detect train data=/content/data/data.yaml model=yolov8n.pt epochs=15 imgsz=640 project=/content/gdrive/MyDrive/ultra_workdir name= fish

 

pretrained된 yolov8 모델을 이용해서 fish image dataset을 전이 학습(trasfer learning)을 시켜줍니다. 

 

이때 사용된 인자는 다음과 같습니다.

  • epoch - image set을 몇 번 학습시킬 것인지에 대한 인자
  • imgsz - 이미지의 사이즈
  • project - 결과를 저장할 directory 위치
  • name - 결과를 저장할 폴더 이름
  • exist_ok - 해당 폴더에 결과 이미 존재한다면 덮어 쓸 것인지

 

가상 터미널에서 train을 시키고 싶다면 아래 주석 처리된 명령어를 입력하면 됩니다. ( !yolo detect train data=/content/data/data.yaml model=yolov8n.pt epochs=15 imgsz=640 project=/content/gdrive/MyDrive/ultra_workdir name= fish )

 

validate 결과
validate 결과

 

학습이 끝나고 validate(검증) 데이터로 성능을 확인한 결과 마지막 class인 Zanclidae -Moorish Idol-(깃대돔? 이라고 합니다.)을 제외하고는 epoch를 15번 돌린거 치고 mAP가 괜찮게 나온 것을 확인할 수 있습니다.

 

model = YOLO("/content/gdrive/MyDrive/ultra_workdir/fish/weights/best.pt") # 가장 성능이 좋았던 모델을 선택

results = model.predict("/content/data/test/images/FishDataset508_png.rf.9c62c3be09fa9f6422f7f2c5e477ac1f.jpg", line_thickness = 2)  

res_plot = results[0].plot()

cv2_imshow(res_plot) # 결과 출력하기

 

이제 학습시킬 때 가장 성능이 좋았던 모델을 선택하고 임의의 test image를 선택하고 detect 시켜봤습니다.

 

detect 결과
detect 결과

 

위와 같이 상어 이미지에서 높은 confidence score로 상어를 잘 detect하는 것을 확인할 수 있습니다.

 

train과 detect이 잘되는 것을 확인했으니 이제 YOLOv8을 사용하여 project을 진행하도록 하겠습니다.  

 

성능을 확인하는 전체 코드는 아래 링크에서 확인할 수 있습니다.

 

https://colab.research.google.com/drive/1IKPzgu4mAbRj7lS_zwzA3zHwVEyVsFxz#scrollTo=eBu_SjzuyMms

 

Google Colaboratory Notebook

Run, share, and edit Python notebooks

colab.research.google.com

 

Reference

https://docs.ultralytics.com/