본 글에서는 YOLO(You Only Look Once) 알고리즘을 사용하여 실시간 객체 검출 애플리케이션을 구축하는 방법을 설명합니다.
YOLO는 고속으로 객체를 탐지할 수 있는 알고리즘으로, 다양한 분야에서 활용되고 있습니다.
OpenCV와 함께 YOLO를 사용하여 웹캠에서 실시간으로 객체를 검출하는 시스템을 만드는 과정을 자세히 설명하겠습니다.
1. YOLO란?
YOLO는 객체 검출을 위해 설계된 신경망 기반의 알고리즘으로, 객체를 탐지할 때 이미지를 여러 개의 그리드로 나누고
각 그리드에서 객체의 경계 상자(bounding box)와 클래스 확률을 예측합니다.
이는 속도가 빠르며 높은 정확도를 자랑하기 때문에 실시간 객체 검출에 적합합니다.
1.1 YOLO의 작동 원리
YOLO는 이미지 전체를 한 번에 처리하는 방식으로 작동합니다. 이 과정은 다음과 같습니다:
- 이미지를 S x S 그리드로 나눈다.
- 각 그리드 셀은 그리드 내에서 객체가 있는 경우, 해당 객체의 경계 상자와 클래스 확률을 예측한다.
- 예측된 경계 상자 및 클래스 확률을 바탕으로 최종 객체 검출 결과를 생성한다.
기본적으로 YOLO는 CNN(Convolutional Neural Network)을 기반으로 하여 객체 탐지를 수행하며,
각각의 그리드 셀에서 객체가 존재할 확률과 함께 경계 상자를 예측합니다.
2. YOLO 모델 다운로드
YOLO 모델을 사용하기 위해서는 학습된 가중치 파일이 필요합니다.
여기서는 YOLOv3 모델을 사용할 것입니다. YOLOv3의 가중치를 다운로드하려면 아래의 명령어를 사용할 수 있습니다.
wget https://pjreddie.com/media/files/yolov3.weights
3. OpenCV 설치
YOLO를 OpenCV와 함께 사용하기 위해 OpenCV 라이브러리를 설치해야 합니다.
Python에서 OpenCV를 설치하려면 pip 명령어를 사용할 수 있습니다.
pip install opencv-python
4. YOLO와 OpenCV 통합
이제 YOLO 모델과 OpenCV를 통합하여 실시간 객체 검출을 수행하는 코드를 작성해보겠습니다.
아래 코드는 웹캠에서 프레임을 읽고 YOLO를 사용하여 객체를 검출하는 예제입니다.
import cv2
import numpy as np
# YOLO 모델 설정 파일 경로
configPath = "yolov3.cfg"
weightsPath = "yolov3.weights"
# 클래스 이름을 가져옵니다.
with open("coco.names", "r") as f:
classes = [line.strip() for line in f.readlines()]
# YOLO 네트워크를 로드합니다.
net = cv2.dnn.readNet(weightsPath, configPath)
# 웹캠을 오픈합니다.
cap = cv2.VideoCapture(0)
while True:
# 웹캠에서 프레임을 읽어 옵니다.
_, frame = cap.read()
height, width, _ = frame.shape
# YOLO의 입력으로 사용할 blob을 생성합니다.
blob = cv2.dnn.blobFromImage(frame, 0.00392, (416, 416), (0, 0, 0), True, crop=False)
net.setInput(blob)
# 네트워크의 출력을 가져옵니다.
layerNames = net.getLayerNames()
outputLayers = [layerNames[i[0] - 1] for i in net.getUnconnectedOutLayers()]
outputs = net.forward(outputLayers)
boxes = []
confidences = []
classIDs = []
# 출력을 분석하여 객체 정보를 획득합니다.
for output in outputs:
for detection in output:
scores = detection[5:]
classID = np.argmax(scores)
confidence = scores[classID]
if confidence > 0.5: # 신뢰도가 0.5 이상인 경우만 처리
# 객체의 위치를 계산합니다.
centerX = int(detection[0] * width)
centerY = int(detection[1] * height)
w = int(detection[2] * width)
h = int(detection[3] * height)
# 직사각형의 좌상단 좌표를 계산합니다.
x = int(centerX - w / 2)
y = int(centerY - h / 2)
boxes.append([x, y, w, h])
confidences.append(float(confidence))
classIDs.append(classID)
# 비최대 억제(Non-Maximum Suppression)를 적용합니다.
indexes = cv2.dnn.NMSBoxes(boxes, confidences, 0.5, 0.4)
# 최종적으로 결과를 화면에 표시합니다.
for i in range(len(boxes)):
if i in indexes:
x, y, w, h = boxes[i]
label = str(classes[classIDs[i]])
cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 2)
cv2.putText(frame, label, (x, y + 30), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 255), 2)
# 결과 프레임을 화면에 표시합니다.
cv2.imshow("YOLO Object Detection", frame)
# 'q' 키를 눌러 종료합니다.
if cv2.waitKey(1) & 0xFF == ord('q'):
break
# 웹캠과 창을 종료합니다.
cap.release()
cv2.destroyAllWindows()
5. 코드 설명
위 코드는 웹캠에서 실시간으로 객체를 탐지하는 전체 애플리케이션입니다.
코드의 주요 부분을 살펴보면 다음과 같습니다:
cv2.VideoCapture(0)
: 기본 웹캠을 열기 위한 코드입니다.cv2.dnn.blobFromImage()
: YOLO 모델의 입력으로 사용할 블롭(blob)을 생성합니다.net.forward()
: 네트워크를 통해 출력을 가져옵니다.- 비최대 억제를 통해 검출된 여러 객체들 중에서 가장 신뢰도가 높은 것만을 계수합니다.
6. 성능 향상을 위한 팁
YOLO의 성능을 향상시키기 위한 몇 가지 팁은 다음과 같습니다:
-
신뢰도 임계값 조정:
confidence > 0.5
로 설정된 신뢰도 임계값을 조정하여 검출 정확도를 개선할 수 있습니다. -
이미지 크기 조정: 입력 이미지 크기를 조정하여 처리 속도를 높일 수 있습니다.
blobFromImage()
의 두 번째 인자로 조정 가능합니다. - 다양한 YOLO 모델 사용: 최신 YOLO 버전(n, YOLOv5 등) 등을 사용하여 성능을 높일 수 있습니다.
7. 결론
본 강좌에서는 YOLO를 이용한 실시간 객체 검출 애플리케이션을 구축하는 방법을 알아보았습니다.
OpenCV와 결합하여 쉽게 사용할 수 있으며, 다양한 응용 프로그램에 활용이 가능합니다.
YOLO의 장점을 잘 이해하고, 효과적으로 실시간 객체 검출 시스템을 구축해보시기 바랍니다.