반응형

윤곽선 검출은 이미지 내 객체의 경계를 찾아내는 방법으로, 주로 이미지에서 객체를 분리하거나 추적할 때 사용됩니다. OpenCV에서 findContours 함수를 이용해 윤곽선을 검출할 수 있습니다. 윤곽선은 연속된 경계의 좌표 목록으로 반환되며, 이를 활용해 윤곽선을 그리거나 특정 모양을 검출할 수 있습니다.

Import packages

import cv2
import numpy as np
import matplotlib.pyplot as plt

Function to Display Images in Jupyter Notebook

Jupyter Notebook 및 Google Colab에서 이미지를 표시할 수 있도록 Function으로 정의합니다.

def img_show(title='image', img=None, figsize=(8, 5)):
    plt.figure(figsize=figsize)

    if type(img) == list:
        titles = title if type(title) == list else [title] * len(img)

        for i in range(len(img)):
            rgbImg = cv2.cvtColor(img[i], cv2.COLOR_GRAY2RGB) if len(img[i].shape) <= 2 else cv2.cvtColor(img[i], cv2.COLOR_BGR2RGB)
            plt.subplot(1, len(img), i + 1)
            plt.imshow(rgbImg)
            plt.title(titles[i])
            plt.xticks([]), plt.yticks([])

        plt.show()
    else:
        rgbImg = cv2.cvtColor(img, cv2.COLOR_GRAY2RGB) if len(img.shape) < 3 else cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
        plt.imshow(rgbImg)
        plt.title(title)
        plt.xticks([]), plt.yticks([])
        plt.show()

Load Image

이미지를 불러옵니다.

cv2_image = cv2.imread('asset/images/test_image.jpg')
gray_image = cv2.cvtColor(cv2_image, cv2.COLOR_BGR2GRAY)

1. 이미지 이진화 (Binary Thresholding)

윤곽선 검출을 하기 전에 이미지를 이진화(흑백)하여 경계선만 남기도록 만듭니다. threshold 함수를 사용해 간단한 이진화를 적용할 수 있습니다.

ret, thresh_image = cv2.threshold(gray_image, 50, 255, cv2.THRESH_BINARY)
img_show(["Original Image", "Thresholded Image"], [cv2_image, thresh_image])

2. 윤곽선 검출 (Contour Detection)

findContours 함수를 사용하여 이미지에서 윤곽선을 검출합니다. 검출된 윤곽선은 contours 리스트에 저장되며, 각 윤곽선의 좌표 정보를 가지고 있습니다.

contours, hierarchy = cv2.findContours(thresh_image, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
print(f"Number of contours found: {len(contours)}")
  • RETR_EXTERNAL: 가장 바깥쪽 윤곽선만 검출합니다.
  • CHAIN_APPROX_SIMPLE: 윤곽선의 꼭짓점만 저장하여 메모리 사용을 줄입니다.

3. 윤곽선 그리기 (Draw Contours)

검출된 윤곽선을 원본 이미지에 그려서 시각화할 수 있습니다. drawContours 함수를 사용하여 윤곽선을 그립니다.

contour_image = cv2_image.copy()
cv2.drawContours(contour_image, contours, -1, (0, 255, 0), 10)
img_show("Contours", contour_image)
  • contours: 검출된 윤곽선 리스트
  • -1: 모든 윤곽선을 그립니다. 특정 윤곽선만 그리려면 인덱스를 사용합니다.
  • (0, 255, 0): 윤곽선의 색상 (녹색)
  • 10: 윤곽선 두께

4. 윤곽선의 특징 계산

윤곽선 검출 후 각 윤곽선의 면적과 둘레를 계산할 수 있습니다. 예를 들어, 첫 번째 윤곽선의 면적과 둘레는 다음과 같이 계산할 수 있습니다.

# 첫 번째 윤곽선의 면적과 둘레
area = cv2.contourArea(contours[0])
perimeter = cv2.arcLength(contours[0], True)

print(f"Contour Area: {area}")
print(f"Contour Perimeter: {perimeter}")

5. 윤곽선 근사화 및 경계 상자 그리기

윤곽선의 복잡도를 줄이기 위해 근사화하여 경계 상자(Rectangle) 또는 다각형을 그릴 수 있습니다. 이 방법은 특정 모양을 검출할 때 유용합니다.

# 윤곽선을 직사각형 경계 상자로 표시
for contour in contours:
    x, y, w, h = cv2.boundingRect(contour)
    cv2.rectangle(contour_image, (x, y), (x + w, y + h), (255, 255, 255), 10)

img_show("Bounding Boxes", contour_image)

위 코드에서는 각 윤곽선을 둘러싸는 경계 상자를 생성하고, 이를 이미지에 그립니다.

요약

윤곽선 검출은 이미지에서 객체를 식별하고, 모양과 크기 분석을 수행하는 데 유용한 기법입니다. OpenCV를 사용해 다양한 윤곽선 검출 방법을 적용하고, 특징을 추출하여 이미지 분석에 활용할 수 있습니다.

반응형