데이터 엔지니어링/Python

[OpenCV] 이미지 분석 시작하기 - 유사도 분석

seojeon9 2024. 2. 29. 14:30

오늘의 목표는 두 개의 이미지의 유사도를 반환해 낼 거다.

1. 히스토그램 비교

가장 일반적인 방법인 히스토그램은 이미지의 각 픽셀 값의 빈도를 나타내는 그래프로, 픽셀 값들의 분포를 알 수 있다.

import cv2
import numpy as np

# 이미지 불러오기
img1 = cv2.imread('image1.jpg')
img2 = cv2.imread('image2.jpg')

# 히스토그램 계산
hist1 = cv2.calcHist([img1], [0, 1, 2], None, [256, 256, 256], [0, 256, 0, 256, 0, 256])
hist2 = cv2.calcHist([img2], [0, 1, 2], None, [256, 256, 256], [0, 256, 0, 256, 0, 256])

# 히스토그램 비교
similarity = cv2.compareHist(hist1, hist2, cv2.HISTCMP_CORREL)
print(f"Histogram Similarity: {similarity}")

히스토그램 기반 유사도를 사용했을 때의 장단점은

장점
단순하고 빠르게 계산이 가능하다.
이미지의 전반적인 분포를 고려하기 때문에 일부 변형에 강한 성능을 봉리 수 있다.
(이미지의 크기와 해상도에 크게 영향을 받지 않는다.)

단점
히스토그램만으로는 이미지의 구조적 특성을 고려하지 않는다.
일부 색상 변화가 크지 않은 이미지에서는 제한된 성능을 보일 수 있다.
(질감이나 모양과 같은 다른 요소를 고려하지 못하고 색상에 대한 정보만을 고려한다.

 

2. 구조적 유사도(SSIM)

SSIM은 이미지의 구조적 유사성을 측정하는 방법이다.

pip install scikit-image

 

from skimage.metrics import structural_similarity as ssim

# 이미지 불러오기
img1 = cv2.imread('image1.jpg')
img2 = cv2.imread('image2.jpg')

# SSIM 계산
similarity_index, _ = ssim(img1, img2, full=True)
print(f"SSIM: {similarity_index}")

구조적 유사도의 장단점으로는

장점
이미지의 밝기, 대비 및 주조적 유사성을 고려하여 높은 정확도를 제공한다.
인간 시각 체계에 기반하고 있어 인간의 시각적 인식과 관련이 높다.

단점
계산 비용이 높아 대규모 이미지 데이터셋에 적용하기 어려울 수 있다.
이미지의 크기가 서로 다를 때 일부 적용 어려움이 있을 수 있다.

 

3. ORB 특징 매칭

ORB는 특징점을 찾아서 이미지 간의 매칭을 수행합니다. 'cv2.ORB_create()' 함수를 사용하여 ORB 디텍터와 매처를 생성하고 'detectAndCompute()' 메서드를 사용하여 특징점을 찾고 매칭할 수 있다.

import cv2

# 이미지 불러오기
img1 = cv2.imread('image1.jpg', 0)
img2 = cv2.imread('image2.jpg', 0)

# ORB 디텍터 및 매처 생성
orb = cv2.ORB_create()

# 특징점 및 디스크립터 계산
kp1, des1 = orb.detectAndCompute(img1, None)
kp2, des2 = orb.detectAndCompute(img2, None)

# BFMatcher 생성 및 매칭
bf = cv2.BFMatcher(cv2.NORM_HAMMING, crossCheck=True)
matches = bf.match(des1, des2)

# 매칭 결과를 정렬하여 가장 좋은 매칭 추출
matches = sorted(matches, key=lambda x: x.distance)

# 매칭 결과 그리기
img_matches = cv2.drawMatches(img1, kp1, img2, kp2, matches[:10], None, flags=cv2.DrawMatchesFlags_NOT_DRAW_SINGLE_POINTS)
cv2.imshow("Matches", img_matches)
cv2.waitKey(0)
cv2.destroyAllWindows()

ORB 특징 매칭의 장단점으로는

장점
회전, 크기 변화에 강한 특징을 찾을 수 있다.
매칭 결과를 시각적으로 확인할 수 있어 디버깅 및 분석이 용이하다.

단점
이미지의 일부 영역이나 텍스처가 부족한 경우에는 제대로 작동하지 않을 수 있다.
특징점 기반의 방법이므로 변형이 심한 이미지에는 적합하지 않을 수 있다.

 


 

상황에 따라 여러 방법을 결합하여 높은 정확도의 유사도 분석을 수행하기도 한다.

히스토그램과 구조적 유사도를 함께 사용하여 최종 유사도를 계산해 보자

import cv2
from skimage.metrics import structural_similarity as ssim

def calculate_histogram_similarity(img1, img2):
    # 히스토그램 계산
    hist1 = cv2.calcHist([img1], [0, 1, 2], None, [256, 256, 256], [0, 256, 0, 256, 0, 256])
    hist2 = cv2.calcHist([img2], [0, 1, 2], None, [256, 256, 256], [0, 256, 0, 256, 0, 256])

    # 히스토그램 비교
    hist_similarity = cv2.compareHist(hist1, hist2, cv2.HISTCMP_CORREL)
    return hist_similarity

def calculate_ssim(img1, img2):
    # SSIM 계산
    similarity_index, _ = ssim(img1, img2, full=True)
    return similarity_index

def combined_similarity(img1, img2, weight_hist=0.5, weight_ssim=0.5):
    # 히스토그램 유사도 계산
    hist_similarity = calculate_histogram_similarity(img1, img2)

    # SSIM 유사도 계산
    ssim_similarity = calculate_ssim(img1, img2)

    # 가중 평균하여 종합적인 유사도 계산
    combined_similarity = (weight_hist * hist_similarity) + (weight_ssim * ssim_similarity)
    return combined_similarity

# 이미지 불러오기
img1 = cv2.imread('image1.jpg')
img2 = cv2.imread('image2.jpg')

# 종합적인 유사도 계산
similarity = combined_similarity(img1, img2)

print(f"Combined Similarity: {similarity}")

각 결과 값을 계산한 후 가중 평균하여 종합적인 유사도를 계산할 수 있다.

이때 weight_histweight_ssim 매개변수는 각각의 유사도에 대한 가중치를 조절하는 데 사용된다.

728x90