이번에 Object Detection 경진대회를 나가게 되면서 YOLOv8을 사용해보게 되었다.

이번 글에서는 YOLO라는 모델에 대한 자세한 설명보다는, 

Custom Dataset을 어떻게 YOLOv8에 Training 시키는지에 대한 자세한 설명과 코드 위주로 정리해보고자 한다.


1. YOLOv8이란?

우선, 기본적으로 YOLO(You Only Look Once)라는 모델은 객체 탐지(Object Detection)를 위한 딥러닝 모델 중 하나로서, 실시간 객체 탐지 및 분류 태스크에 널리 사용된다.

공식 깃허브 : 

 

GitHub - ultralytics/ultralytics: NEW - YOLOv8 🚀 in PyTorch > ONNX > OpenVINO > CoreML > TFLite

NEW - YOLOv8 🚀 in PyTorch > ONNX > OpenVINO > CoreML > TFLite - GitHub - ultralytics/ultralytics: NEW - YOLOv8 🚀 in PyTorch > ONNX > OpenVINO > CoreML > TFLite

github.com

2. YOLOv8 설치

아래 코드를 실행해서 yolov8를 설치해주자.

!pip install ultralytics

3. Custom Dataset 구조

가장 애를 먹었던 부분인데, 바로 데이터셋 구조 설정이다. 다음 그림과 같은 파일 구조를 띄도록 해준다. 

yolov8 파일 구조

경로 설정에 계속 문제가 생기면 상대경로 말고 절대경로로 지정하는 것을 추천한다.

4. coco8.yaml 파일 설정 

  • path : dataset root 경로
  • train : training set 경로
  • val : validation set 경로
  • test : test set 경로
  • classes : 클래스 정보
# Train/val/test sets as 1) dir: path/to/imgs, 2) file: path/to/imgs.txt, or 3) list: [path/to/imgs1, path/to/imgs2, ..]
path: ../datasets/coco8  # dataset root dir
train: images/train  # train images (relative to 'path') 4 images
val: images/val  # val images (relative to 'path') 4 images
test:  # test images (optional)

# Classes (80 COCO classes)
names:
  0: person
  1: bicycle
  2: car
  ...
  77: teddy bear
  78: hair drier
  79: toothbrush

5. Training

다음 코드를 실행하여 Training 해주자.

from ultralytics import YOLO

# Load a model
model = YOLO('yolov8n.pt')  # load a pretrained model (recommended for training)

# Train the model
results = model.train(data='coco8.yaml', epochs=100, imgsz=640)

6. Inference

from ultralytics import YOLO

# 위에서 Trained된 모델 불러오기
model = YOLO('yolov8n.pt')

# inference 하고 싶은 이미지 불러오기
source = 'path/to/image.jpg'

# Run inference on the source
results = model(source)  # list of Results objects
반응형
SMALL

1. LeNet-5란?

LeNet-5은 1998년에 개발된 초기 CNN 구조로, 이후 딥러닝의 기반을 마련한 모델이라고 할 수 있다.

LeNet-5 구조


2. 각 Layer 살펴보기

(1) Input Layer (입력층) 

LeNet-5의 입력은 32x32 크기의 흑백 이미지이다. Input 이미지는 0과 1 사이의 값으로 정규화된다.

(2) C1 Layer (Convolution)

LeNet-5는 두 개의 Convolution Layer을 가지고 있는데, 첫 번째 Convolution layer는 6개의 5x5 크기의 필터를 사용한다. 합성곱 연산 결과 6장의 28x28 feature map을 얻게 된다. 활성화 함수는 sigmoid 함수를 사용한다.

(3) S2 Layer (Subsampling)

Convolution layer 이후 평균 풀링을 진행한다. 2x2 window와 stride 2를 사용하여 feature map이 반으로 줄어든다. 즉, 결과적으로 6장의 14x14 feature map을 얻게 된다.

(4) C3 Layer (Convolution)

두번째 Convolution layer는 첫 번째 합성곱 레이어와 유사한 구조를 가지고 있지만, feature map의 깊이가 6에서 16으로 증가한다. 이 층에서도 활성화 함수는 sigmoid 함수를 사용한다. 

(5) S4 Layer (Subsampling)

첫 번째 평균 풀링 layer와 마찬가지로 2x2 window와 stride 2를 사용하여 입력 이미지의 공간 해상도를 다시 줄입니다. 

(6) C5 Layer (Convolution)

16장의 5 x 5 특성맵을 120개의 5 x 5 x 16 사이즈의 필터와 합성곱 연산을 진행한다. 결과적으로 120개의 1 x 1 feature map이 나온다.

(7) F6 (Fully Connected Layer)

이제 입력 이미지는 Fully Connected Layer로 전달된다. 이 layer는 86개의 뉴런으로 구성되어 있으며, 이전 layer의 모든 feature map과 연결된다. Fully Connected Layer는 입력에 대한 weight 합과 bias을 계산하고, sigmoid 활성화 함수를 사용한다.

(8) Output Layer (출력층)

LeNet-5의 출력층은 10개의 뉴런으로 구성되어 있다. 이 레이어는 입력 이미지가 0부터 9까지의 숫자를 나타내는 확률 분포로 매핑되도록 설계되었다. 출력 뉴런 중 가장 높은 값을 가진 뉴런이 모델의 예측 결과로 사용되는 것이다.


3. Tensorflow 코드 구현하기

(1) 필요 라이브러리 가져오기

import numpy as np
import tensorflow as tf
import tensorflow.keras.datasets as ds

from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Conv2D,MaxPooling2D,Flatten,Dropout,Dense
from tensorflow.keras.optimizers import Adam

(2) 데이터셋 전처리 

(x_train,y_train),(x_test,y_test)=ds.mnist.load_data()
x_train=x_train.reshape(60000,28,28,1) # 60000개의 데이터 -> 28x28x1 (grayscale)
x_test=x_test.reshape(10000,28,28,1) # 10000개의 데이터 -> 28x28x1 (grayscale)

x_train=x_train.astype(np.float32)/255.0 # 0~255의 픽셀 값 -> 0~1 사이의 값으로 정규화
x_test=x_test.astype(np.float32)/255.0

y_train=tf.keras.utils.to_categorical(y_train,10) # 0~9 값을 원핫 코드로 변환
y_test=tf.keras.utils.to_categorical(y_test,10)

(3) 층 쌓기

cnn=Sequential()
# C1 : 6개 5x5 filter, zero padding -> output_shape = (28, 28, 6)
cnn.add(Conv2D(6,(5,5),padding='same',activation='relu',input_shape=(28,28,1)))

# S2 : 2x2 filter, stride = 2 -> output_shape = (14, 14, 6)
cnn.add(MaxPooling2D(pool_size=(2,2),strides=2))

# C3 : 16개 5x5 filter, padding 안함 -> output_shape = (10, 10, 16)
cnn.add(Conv2D(16,(5,5),padding='valid',activation='relu'))

# S4  : 2x2 filter, stride = 2 -> output_shape = (5, 5, 16)
cnn.add(MaxPooling2D(pool_size=(2,2),strides=2))

# C5 : 120개 5x5 filter, padding 안함 -> output_shape = (1, 1, 120)
cnn.add(Conv2D(120,(5,5),padding='valid',activation='relu'))

# 120
cnn.add(Flatten())

# 120 -> 84
cnn.add(Dense(units=84,activation='relu'))

# 84 -> 10
cnn.add(Dense(units=10,activation='softmax'))

(4) 학습, 정확도 계산

cnn.compile(loss='categorical_crossentropy',optimizer=Adam(learning_rate=0.001),metrics=['accuracy'])
cnn.fit(x_train,y_train,batch_size=128,epochs=50,validation_data=(x_test,y_test),verbose=2)

res=cnn.evaluate(x_test,y_test,verbose=0)
print('accuracy=',res[1]*100)

 

반응형
SMALL

본 포스팅에서는 OpenCV Python을 활용하여 얼굴 검출을 수행하는 방법을 소개합니다. 얼굴 검출은 컴퓨터 비전 분야에서 매우 중요한 작업 중 하나로, 이미지나 비디오에서 얼굴을 자동으로 인식하는 기술을 말합니다. 여기서는 하르 캐스케이드(Haar Cascade)라고 하는 객체 검출기를 사용하였고, 실행 환경은 Google Colab에서 실행하였습니다. 

1. OpenCV 설치하기

OpenCV가 설치되어 있지 않은 분들만 다음 코드를 콜랩에서 실행하여 설치해 주시면 됩니다.

!pip install opencv-python

2. Haar Cascade 파일 다운로드

얼굴 검출을 위해 미리 학습된 Haar Cascade 파일이 필요합니다. OpenCV 공식 GitHub 저장소에서 다양한 학습된 모델을 제공하고 있으며, 다음 링크로 들어가셔서 얼굴 검출에 사용할 "haarcascade_frontalface_default.xml" 파일을 다운로드해주시면 됩니다. 

https://github.com/opencv/opencv/blob/master/data/haarcascades/haarcascade_frontalface_default.xml

 

GitHub - opencv/opencv: Open Source Computer Vision Library

Open Source Computer Vision Library. Contribute to opencv/opencv development by creating an account on GitHub.

github.com

3. OpenCV 라이브러리 임포트하기

준비 단계는 모두 마쳤고, 이제 본격적으로 얼굴 검출을 진행해보겠습니다. 우선, 다음 코드를 실행하여 OpenCV 라이브러리를 import 해줍니다.

import cv2

4. 구글 드라이브 마운트

구글 드라이브에 있는 파일을 사용하기 위해서 구글 드라이브를 마운트 해줍니다. 다음 코드를 실행만 해주시면 됩니다.

from google.colab import drive
drive.mount('/content/drive')

5. Haar Hascade 경로 설정해 주기

경로는 haarcascade_frontalface_default.xml 파일의 경로로 변경해 주시면 됩니다. 저는 드라이브에서 face 폴더 안에 이 파일을 넣어두었습니다.

# Haar Cascade 파일 경로
cascade_path = '/content/drive/MyDrive/face/haarcascade_frontalface_default.xml'

6. 이미지 읽기

다음으로 얼굴을 검출할 이미지를 불러옵니다. 저는 드라이브에 미리 저장해 두었던 방탄소년단 이미지를 불러왔습니다. 이미지의 형식은 jpeg, jpg 모두 상관없습니다. 

# 이미지 읽기
image_path = '/content/drive/MyDrive/face/bts.jpeg'
image = cv2.imread(image_path)

7. GrayScale로 변경

Haar Cascade는 GrayScale 이미지, 즉 흑백 이미지에서 얼굴을 검출하기 때문에 우리의 이미지 또한 흑백 이미지로 바꿔주어야 합니다. 다음 코드를 실행하시면 이미지를 GrayScale 이미지로 바꾸실 수 있습니다.

gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

 

8. 얼굴 검출용 CascadeClassifier 객체 생성

CascadeClassifier 클래스의 인스턴스를 생성하여 얼굴 검출에 사용할 Haar Cascade 파일을 로드합니다.

face_cascade = cv2.CascadeClassifier(cascade_path)

9. 얼굴 검출

detectMultiScale 함수를 사용하여 얼굴을 검출합니다. 첫 번째 인자로는 그레이스케일 이미지를 전달하고, scaleFactor, minNeighbors, minSize와 같은 매개변수를 조정하여 얼굴 검출의 성능을 조절할 수 있습니다.

faces = face_cascade.detectMultiScale(gray, scaleFactor=1.1, minNeighbors=5, minSize=(30, 30))

10. 검출된 얼굴 주변에 사각형 그리기

검출된 얼굴 주위에 사각형을 그려줍니다. 검출된 얼굴의 좌표와 너비, 높이를 사용하여 사각형의 좌표를 계산하고, 그립니다. 이 코드에서는 사각형의 색상을 (0, 255, 0)으로, 두께를 3으로 설정하였습니다.

for (x, y, w, h) in faces:
    cv2.rectangle(image, (x, y), (x+w, y+h), (0, 255, 0), 3)

11. 결과 이미지 출력

다음 코드로 얼굴에 사각형이 그려진 이미지를 출력해 볼 수 있습니다. 

from google.colab.patches import cv2_imshow
cv2_imshow(image)
cv2.waitKey(0)
cv2.destroyAllWindows()

전체 코드

import cv2
from google.colab.patches import cv2_imshow

# Haar Cascade 파일 경로
cascade_path = '/content/drive/MyDrive/face/haarcascade_frontalface_default.xml'

# 이미지 읽기
image_path = '/content/drive/MyDrive/face/bts.jpeg'
image = cv2.imread(image_path)

# 그레이스케일 변환
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

# 얼굴 검출용 CascadeClassifier 객체 생성
face_cascade = cv2.CascadeClassifier(cascade_path)

# 얼굴 검출
faces = face_cascade.detectMultiScale(gray, scaleFactor=1.1, minNeighbors=5, minSize=(30, 30))

# 검출된 얼굴 주변에 사각형 그리기
for (x, y, w, h) in faces:
    cv2.rectangle(image, (x, y), (x+w, y+h), (0, 255, 0), 3)

# 결과 이미지 출력
cv2_imshow(image)
cv2.waitKey(0)
cv2.destroyAllWindows()

결과 이미지

방탄소년단(bts) 이미지에서 멤버 얼굴 검출하기

하나만 하기에는 아쉬워서 걸그룹 아이브 얼굴도 검출해 보았다.

아이브 이미지에서 멤버 얼굴 검출하기


결론

살짝 정확도가 떨어지는 것 같기는 하지만, 단순 코드 몇 줄로 이렇게 얼굴을 검출할 수 있다는 것이 놀라웠다. 다음 글에서는 얼굴 검출뿐만 아니라 눈 검출이나 다른 것들도 시도해보려고 한다. 

반응형
SMALL

OpenCV란? 

 

OpenCV는 "Open Source Computer Vision Library"의 약자로, 이미지 처리 및 컴퓨터 비전 분야 개발하는 데 사용되는 라이브러리입니다. C++, Python, Java 등 다양한 프로그래밍 언어에서 사용할 수 있고, 본 글에서는 Python을 사용하여 OpenCV를 설치하는 방법을 알아봅니다.

 

OpenCV 설치하기

 

OpenCV는 pip를 통하여 설치할 수 있습니다. 파이썬 3.x를 설치한 후 다음 명령어를 사용하여 OpenCV를 설치 합니다.

# pip 명령어로 설치
pip install opencv-python

 

정상적으로 설치 되었다면 다음 코드를 실행하였을 때 설치한 OpenCV의 버전이 출력됩니다.

import cv2
print(cv2.__version__)

 

[간단한 예제 코드]

아래는 간단한 예제 코드입니다. 이미지를 불러와서 회색으로 변환한 후 화면에 출력하는 코드입니다.

import cv2

# 이미지 파일을 읽어옵니다.
image = cv2.imread('image.jpg')

# 이미지를 회색조로 변환합니다.
gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

# 변환된 이미지를 화면에 표시합니다.
cv2.imshow('Gray Image', gray_image)
cv2.waitKey(0)
cv2.destroyAllWindows()
반응형
SMALL

Data Augmentation이란?

데이터 증강(data augmentation)은 딥러닝 기반의 컴퓨터 비전 분야에서 중요한 역할을 한다. 데이터 증강은 제한된 양의 훈련 데이터를 더 다양한 형태로 변형시켜 모델의 성능을 향상시키는 것을 목표로 한다. 이번 글에서는 OpenCV를 활용한 Data Augmentation을 구현하는 것을 목표로 한다.

1. 이미지 불러오기 및 표시

먼저 OpenCV를 사용하여 이미지를 불러오고 imshow()를 사용하여 이미지를 표시한다.

import cv2

# 이미지 파일 경로
image_path = "image.jpg"

# 이미지 불러오기
image = cv2.imread(image_path)

# 이미지 표시
cv2.imshow("Original Image", image)
cv2.waitKey(0)
cv2.destroyAllWindows()

2. 이미지 회전

getRotationMatrix2D()warpAffine()를 사용하여 이미지를 회전시킬 수 있다. 아래의 코드는 45도만큼 시계 방향으로 이미지를 회전하는 코드이다. 

# 이미지 회전
rows, cols, _ = image.shape
M = cv2.getRotationMatrix2D((cols / 2, rows / 2), 45, 1)
rotated_image = cv2.warpAffine(image, M, (cols, rows))

# 이미지 표시
cv2.imshow("Rotated Image", rotated_image)
cv2.waitKey(0)
cv2.destroyAllWindows()

[결과 이미지]

45도만큼 시계방향으로 회전

3. 이미지 반전

flip()를 사용하여 이미지를 반전시킬 수 있다. 아래 코드는 이미지를 좌우로 반전시키는 코드이다. 

# 이미지 반전
flipped_image = cv2.flip(image, 1)

# 이미지 표시
cv2.imshow("Flipped Image", flipped_image)
cv2.waitKey(0)
cv2.destroyAllWindows()

[결과 이미지]

좌우 반전

4. 이미지 밝기 조절

이미지의 밝기를 조절하여 데이터셋을 변형시킬 수도 있다. convertTo()를 사용하면 된다. 아래 코드는 이미지의 밝기를 50만큼 증가시킨 코드이다. 

# 이미지 밝기 조절
brightened_image = np.clip(image.astype(np.int16) + 50, 0, 255).astype(np.uint8)

# 이미지 표시
cv2.imshow("Brightened Image", brightened_image)
cv2.waitKey(0)
cv2.destroyAllWindows()

[결과 이미지]

밝기 +50

5. 그 외의 기법

1) 이미지 크기 조절 : resize()

2) 가우시안 노이즈 추가 : randn(), add()

3) 색상 변환 : cvtColor()

 

 

반응형
SMALL

+ Recent posts