Python SciPy

SciPy 레이블링과 객체 분석 (SciPy.ndimage)

PyExplorer 2025. 3. 30. 10:47
728x90

SciPy 레이블링과 객체 분석 (SciPy.ndimage)

이미지 처리에서 중요한 작업 중 하나는 이미지 내의 특정 객체를 식별하고 분석하는 것입니다. 특히 이진 이미지에서 특정 형태를 가진 객체를 분리하고 개별적으로 분석하는 과정은 많은 이미지 처리 응용 프로그램에서 필요합니다. Python의 SciPy 라이브러리 중 scipy.ndimage 모듈은 이러한 작업을 효과적으로 수행할 수 있도록 다양한 기능을 제공합니다. 그중에서도 레이블링(Labeling)객체 분석(Object Analysis)은 이미지 내의 객체를 식별하고 속성을 추출하는 데 유용한 도구입니다.

이 글에서는 SciPy의 ndimage 모듈을 활용해 이진 이미지에서 객체를 레이블링하고, 각 객체의 특징을 분석하는 방법에 대해 상세히 알아보겠습니다.


1. 레이블링(Labeling)이란?

레이블링(Labeling)은 이진 이미지에서 연결된 영역(Connected Components)을 식별하고, 각 영역에 고유한 레이블을 부여하는 과정입니다. 예를 들어, 흑백 이미지에서 흰색 픽셀로 구성된 서로 다른 두 개의 객체가 있을 때, 각 객체를 다른 레이블로 구분하는 것입니다.

SciPy에서는 scipy.ndimage.label 함수를 사용하여 레이블링을 수행할 수 있습니다. 이 함수는 다음과 같은 결과를 반환합니다:

  • labeled_array: 각 객체에 고유 번호가 부여된 배열
  • num_features: 식별된 객체의 수

예제: 간단한 이진 이미지에서 레이블링 수행

아래는 작은 이진 이미지에서 레이블링을 수행하는 예제입니다.

import numpy as np
from scipy.ndimage import label

# 샘플 이진 이미지
binary_image = np.array([[0, 0, 1, 1, 0, 0],
                         [0, 1, 1, 1, 0, 0],
                         [0, 0, 0, 1, 0, 1],
                         [1, 1, 0, 0, 0, 1],
                         [0, 1, 1, 0, 0, 0]])

# 레이블링 수행
labeled_array, num_features = label(binary_image)

print("레이블 배열:\n", labeled_array)
print("객체 수:", num_features)

출력 결과

레이블 배열:
 [[0 0 1 1 0 0]
  [0 1 1 1 0 0]
  [0 0 0 1 0 2]
  [3 3 0 0 0 2]
  [0 3 3 0 0 0]]

객체 수: 3

위 결과에서, 총 3개의 서로 다른 객체가 식별되었으며, 각 객체는 1, 2, 3의 레이블로 표시되었습니다.


2. 연결성(Connectivity)

레이블링을 수행할 때, 객체의 연결성을 정의하는 것이 중요합니다. 연결성은 픽셀이 서로 연결되었다고 판단하는 기준을 의미하며, 일반적으로 4-연결성(4-connected)과 8-연결성(8-connected)을 사용합니다.

  • 4-연결성: 상하좌우 방향으로 연결된 픽셀만을 연결된 영역으로 간주합니다.
  • 8-연결성: 대각선을 포함해 주변 8개 방향의 픽셀을 연결된 영역으로 간주합니다.

scipy.ndimage.label 함수에서는 structure 매개변수를 사용하여 연결성을 정의할 수 있습니다.

예제: 8-연결성 레이블링 수행

# 8-연결성을 위한 구조 요소 정의
structure = np.array([[1, 1, 1],
                      [1, 1, 1],
                      [1, 1, 1]])

# 8-연결성을 기준으로 레이블링 수행
labeled_array, num_features = label(binary_image, structure=structure)

print("8-연결성 레이블 배열:\n", labeled_array)
print("객체 수:", num_features)

3. 객체 속성 분석

레이블링이 완료된 후에는 각 객체의 속성을 분석할 수 있습니다. scipy.ndimage 모듈의 다양한 함수를 활용하면 다음과 같은 정보를 쉽게 얻을 수 있습니다.

  • 객체의 크기: ndimage.sum
  • 중심 좌표: ndimage.center_of_mass
  • 바운딩 박스: ndimage.find_objects

예제: 객체 속성 분석

아래는 레이블링된 이미지에서 각 객체의 크기와 중심 좌표를 구하는 예제입니다.

from scipy.ndimage import sum as nd_sum, center_of_mass

# 객체의 크기
object_sizes = nd_sum(binary_image, labeled_array, range(1, num_features + 1))
print("각 객체의 크기:", object_sizes)

# 객체의 중심 좌표
object_centroids = center_of_mass(binary_image, labeled_array, range(1, num_features + 1))
print("각 객체의 중심 좌표:", object_centroids)

출력 결과

각 객체의 크기: [5.0, 2.0, 4.0]
각 객체의 중심 좌표: [(1.2, 2.4), (2.5, 5.0), (3.25, 0.75)]

이와 같이, 객체의 크기와 중심 좌표를 쉽게 확인할 수 있습니다.


4. 실제 이미지에 적용하기

이번에는 실제 이미지를 사용하여 객체를 레이블링하고 분석하는 방법을 살펴보겠습니다. OpenCV와 SciPy를 함께 사용해 이진 이미지를 처리하고 분석하는 과정을 수행합니다.

예제: 이미지에서 객체 레이블링

import cv2
import matplotlib.pyplot as plt

# 이미지 불러오기
image = cv2.imread("sample_image.png", cv2.IMREAD_GRAYSCALE)

# 이진화 수행
_, binary_image = cv2.threshold(image, 128, 255, cv2.THRESH_BINARY)

# 레이블링 수행
labeled_array, num_features = label(binary_image)

# 결과 시각화
plt.figure(figsize=(12, 6))
plt.subplot(1, 2, 1)
plt.title("이진 이미지")
plt.imshow(binary_image, cmap="gray")
plt.axis("off")

plt.subplot(1, 2, 2)
plt.title("레이블링 결과")
plt.imshow(labeled_array, cmap="nipy_spectral")
plt.axis("off")

plt.show()

이 방법을 통해 실제 이미지에서도 레이블링과 객체 분석을 효과적으로 수행할 수 있습니다.


5. 결론

SciPy의 ndimage 모듈을 활용하면 이미지 내의 객체를 효과적으로 식별하고 분석할 수 있습니다. 레이블링은 개별 객체를 구분하고, 크기, 위치, 형태 등 다양한 속성을 분석하는 데 중요한 역할을 합니다.

본 글에서 다룬 주요 내용은 다음과 같습니다:

  1. 레이블링: scipy.ndimage.label을 사용해 이진 이미지 내의 객체를 식별하는 방법
  2. 연결성: 4-연결성과 8-연결성을 정의하는 방법
  3. 객체 분석: 크기, 중심 좌표 등 다양한 속성을 분석하는 방법
  4. 실제 이미지 적용: OpenCV와 함께 실제 이미지에서 레이블링 수행

이러한 방법을 활용하면 다양한 이미지 처리 작업에서 객체 분석을 보다 쉽게 수행할 수 있습니다.

728x90