Python/OpenCV

OpenCV에서 YOLO를 활용한 객체 탐지

임베디드 친구 2025. 11. 16. 12:04
728x90
반응형

OpenCV에서 YOLO를 활용한 객체 탐지

객체 탐지는 컴퓨터 비전 분야에서 중요한 기술 중 하나로, 이미지나 영상에서 객체의 위치를 탐지하고 분류하는 역할을 합니다. 이 글에서는 OpenCV를 활용하여 YOLO(You Only Look Once) 모델을 사용한 객체 탐지 방법을 설명하고, Python 코드 예제를 통해 실제로 YOLO를 활용하는 방법을 살펴보겠습니다.


1. YOLO란?

YOLO(You Only Look Once)는 객체 탐지를 위한 딥러닝 기반 알고리즘 중 하나로, 이미지 전체를 한 번만 분석하여 빠르게 객체를 탐지하는 것이 특징입니다. YOLO는 다음과 같은 장점을 가지고 있습니다:

  • 빠른 속도: 한 번의 전방향 전달(forward pass)로 객체를 탐지하므로 실시간 탐지가 가능합니다.
  • 높은 정확도: 최신 버전(YOLOv4, YOLOv5, YOLOv7 등)은 높은 mAP(mean Average Precision) 성능을 보입니다.
  • 다양한 객체 탐지 가능: COCO, Pascal VOC 등의 데이터셋을 기반으로 학습된 모델을 활용할 수 있습니다.

YOLO는 Darknet이라는 프레임워크로 구현되어 있으며, OpenCV의 DNN 모듈을 이용하면 Python에서 YOLO 모델을 쉽게 사용할 수 있습니다.


2. YOLO 모델 다운로드 및 환경 설정

YOLO를 사용하려면 사전 학습된 가중치 파일과 네트워크 구조를 정의하는 파일이 필요합니다. YOLOv3 또는 YOLOv4 모델을 사용할 수 있으며, 아래의 파일들이 필요합니다:

  • yolov3.weights 또는 yolov4.weights: 학습된 가중치 파일
  • yolov3.cfg 또는 yolov4.cfg: 네트워크 구조 정의 파일
  • coco.names: COCO 데이터셋의 클래스 이름 파일

2.1 파일 다운로드

다음 명령어를 사용하여 YOLO 모델 파일을 다운로드할 수 있습니다:

wget https://pjreddie.com/media/files/yolov3.weights
wget https://raw.githubusercontent.com/pjreddie/darknet/master/cfg/yolov3.cfg
wget https://raw.githubusercontent.com/pjreddie/darknet/master/data/coco.names

3. OpenCV를 활용한 YOLO 객체 탐지 구현

OpenCV의 cv2.dnn 모듈을 활용하여 YOLO 모델을 로드하고 객체 탐지를 수행할 수 있습니다.

3.1 YOLO 모델 로드 및 객체 탐지 코드

아래는 YOLO 모델을 로드하고 객체 탐지를 수행하는 Python 코드입니다.

import cv2
import numpy as np

# YOLO 모델 파일 경로 설정
CONFIG_PATH = "yolov3.cfg"
WEIGHTS_PATH = "yolov3.weights"
NAMES_PATH = "coco.names"

# 클래스 이름 로드
with open(NAMES_PATH, "r") as f:
    class_names = [line.strip() for line in f.readlines()]

# YOLO 모델 로드
net = cv2.dnn.readNet(WEIGHTS_PATH, CONFIG_PATH)

# OpenCV DNN 백엔드 설정 (CUDA 사용 가능)
net.setPreferableBackend(cv2.dnn.DNN_BACKEND_OPENCV)
net.setPreferableTarget(cv2.dnn.DNN_TARGET_CPU)  # GPU 사용 시 DNN_TARGET_CUDA

# 객체 탐지 함수
def detect_objects(image):
    height, width = image.shape[:2]
    blob = cv2.dnn.blobFromImage(image, 1/255.0, (416, 416), swapRB=True, crop=False)
    net.setInput(blob)

    layer_names = net.getLayerNames()
    output_layers = [layer_names[i[0] - 1] for i in net.getUnconnectedOutLayers()]
    detections = net.forward(output_layers)

    boxes, confidences, class_ids = [], [], []
    for output in detections:
        for detection in output:
            scores = detection[5:]
            class_id = np.argmax(scores)
            confidence = scores[class_id]
            if confidence > 0.5:
                center_x, center_y, w, h = (detection[0:4] * [width, height, width, height]).astype(int)
                x = int(center_x - w / 2)
                y = int(center_y - h / 2)
                boxes.append([x, y, w, h])
                confidences.append(float(confidence))
                class_ids.append(class_id)

    indices = cv2.dnn.NMSBoxes(boxes, confidences, 0.5, 0.4)
    for i in indices.flatten():
        x, y, w, h = boxes[i]
        label = f"{class_names[class_ids[i]]}: {confidences[i]:.2f}"
        cv2.rectangle(image, (x, y), (x + w, y + h), (0, 255, 0), 2)
        cv2.putText(image, label, (x, y - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 2)

    return image

# 이미지 불러오기 및 탐지 수행
image = cv2.imread("test.jpg")
detected_image = detect_objects(image)

# 결과 출력
cv2.imshow("YOLO Object Detection", detected_image)
cv2.waitKey(0)
cv2.destroyAllWindows()

4. 코드 설명

  • cv2.dnn.readNet(): YOLO 모델을 로드합니다.
  • blobFromImage(): 이미지를 YOLO 입력 형식으로 변환합니다.
  • net.forward(): YOLO 네트워크를 통해 객체 탐지를 수행합니다.
  • cv2.rectangle(), cv2.putText(): 탐지된 객체를 시각적으로 표시합니다.
  • NMSBoxes(): 비최대 억제(Non-Maximum Suppression)를 적용하여 중복된 박스를 제거합니다.

5. 결론

이 글에서는 OpenCV의 cv2.dnn 모듈을 활용하여 YOLO 모델을 사용한 객체 탐지 방법을 설명하였습니다. YOLO는 빠르고 정확한 객체 탐지가 가능하며, OpenCV를 활용하면 쉽게 구현할 수 있습니다. 향후 YOLOv5, YOLOv7 등의 최신 모델을 적용하여 성능을 비교해보는 것도 좋은 방법입니다.

반응형