본문 바로가기
공부공부/2025 쌓아가는 나의 지식~

[OpenCV / Python] 이미지 유사도(Image Similarity) 측정 [Pixel, Structural, Histogram]

by Lee_story_.. 2025. 3. 19.
728x90

 

이미지 유사도란!

이미지 유사도란 이미지들 사이에서 공통된 특징을 추출하고 이를 수치화하여 얼마나 비슷한지 정량적으로 나타내는 것!

 

 

사진 검색, 추천 시스템, 위조 이미지 탐지, 의료 영상 진단 등 여러 분야에 폭넓게 활용됩니다.

 

 

저는 이번에 GAN모델을 이용해서 생성한 이미지 복원모델이 얼마나! 원본과 동일하게 복원했냐에 대해서 

알아보기 위해서 이미지 유사도 실험을 진행하였습니다. 

 

 

 

 

실험을 진행하기 위해서 다양한 방법들을 알아보는데! 

방법이....... 생각보다 많았습니다....

 

그래서 이번글에서는 해당 방법들을 정리해보고 어떤 특징이 있는지를 찾아보았습니다!

 

그럼 시작!

 

 

 


픽셀 기반 비교 방식 (Pixel-based methods)


 

 

이미지 유사도를 측정하는 가장 단순한 방법으로, 픽셀 값을 직접 비교하여 유사도를 측정하는 방법입니다. 

대표적인 방법으로는 MSE이 있습니다.

 

MSE (Mean Squared Error, 평균 제곱 오차)

  • 픽셀 값 차이의 제곱을 평균 낸 값으로, 값이 작을수록 유사도가 높게 측정됨
  • 계산이 빠르고 간단하지만, 사람의 지각과 잘 맞지 않는 경우가 많음....

 

수식은 다음과 같습니다. 

 

이걸 코드로 작성하면!

def mse(image1, image2):
	## 한 픽셀에서의 두 이미지 차이 제곱
    Value = np.sum((image1.astype("float") - image2.astype("float")) ** 2) 
    Value /= float(image1.shape[0] * image1.shape[1])  ## 전체 픽셀!

    return Value

 

 

코드를 통해 동일한 이미지를 비교하면 아래처럼 0에 가까워지고

 

 

약간이라도 달라지면!

 

아예 다른 이미지라면...차이는 더더 커집니다!

 

 

 

 

 

 


 

구조 기반 비교 방식 (Structural-based methods)


구조 기반 비교 방식은 단순히 각 픽셀의 값만 비교하는 것이 아니라, 이미지 내에 존재하는 구조적 정보를 추출하여 두 이미지 간의 유사성을 평가하는 방법입니다. 이러한 방식은 이미지의 밝기나 색상 변화에 덜 민감하며, 인간의 시각적 인식과 유사한 기준을 제공합니다.

대표적인 방식으로는 SSIM이 있습니다. 

 

  • SSIM (Structural Similarity Index)
    • 밝기, 대비, 구조를 종합적으로 고려한 방식으로 인간의 시각적 인지와 유사한 평가 결과를 도출
    • 0에서 1 사이의 값을 가지며, 1에 가까울수록 이미지가 유사함!

수식은 아래와 같고,

 

해당 계산함수는 skimage라이브러리에서 지원해줍니다!

from skimage.metrics import structural_similarity as ssim

def ssimScore(image1,image2):
    gray1 = cv2.cvtColor(image1, cv2.COLOR_BGR2GRAY) 
    gray2 = cv2.cvtColor(image2, cv2.COLOR_BGR2GRAY)

    ssim_score, _ = ssim(gray1, gray2, full=True)

    return ssim_score

 

사용하기 위해서는 skimage라이브러리를 참조하고,

구조적 특성을 비교하기에 이미지를 GrayScale로 처리해주어야합니다.

 

동일한 사진은 값이 1로!

 

달라질수록 값이 감소합니다...

 

더달라지면...?

 

 

 


히스토그램 비교 방식


 

히스토그램 비교 방식은 이미지의 색상, 밝기, 혹은 다른 특성들의 분포를 히스토그램으로 나타낸 후, 두 이미지 간의 유사성을 평가하는 방법입니다.

각 이미지의 히스토그램은 픽셀 값의 분포를 나타내므로, 히스토그램과 색상분포를 비교하는 알고리즘을 사용하면, 두 이미지의 색상유사도를 비교 할  수 있습니다.

 

 

먼저 각 픽셀의 값 분포를 확인하는 부분입니다.

    ## 히스토그램 유사도
    hsv1 = cv2.cvtColor(image1, cv2.COLOR_BGR2HSV)
    hsv2 = cv2.cvtColor(image2, cv2.COLOR_BGR2HSV)    
	# 히스토그램 계산
    hist1 = cv2.calcHist([hsv1], [0, 1, 2], None, [8, 8, 8], [0, 256, 0, 256, 0, 256])
    hist2 = cv2.calcHist([hsv2], [0, 1, 2], None, [8, 8, 8], [0, 256, 0, 256, 0, 256])

 

cv2에서 제공해주는, calcHist()함수를 이용해서 해당 이미지의 히스토그램을 구할 수 있습니다.

 

 

함수 구성은 아래와 같습니다.

cv2.calcHist(images, channels, mask, histSize, ranges)


images	히스토그램을 계산할 이미지 (리스트 형태로 입력)
channels	히스토그램 계산에 사용할 이미지의 채널을 나타내는 인덱스 ([0,1,2]는 HSV 전체 채널)
mask	계산할 영역의 마스크 (None은 전체 이미지 사용)
histSize	각 채널에서 나눌 구간(bin)의 개수
ranges	각 채널의 값 범위

 

 

 

그리고 히스토그램 비교를 진행할 알고리즘!

 

 

상관계수 ( cv2.HISTCMP_CORREL )

두 이미지의 히스토그램이나 피처 간의 선형 관계를 측정합니다.

값이 1에 가까울수록 유사하고, -1이면 반대의 관계를 의미합니다.

 

카이제곱 거리 ( cv2.HISTCMP_CHISQR )

각 히스토그램 빈(bin) 간 차이의 제곱을 계산해 두 분포의 차이를 측정합니다. 값이 작을수록 두 이미지가 유사하다고 판단합니다.

 

 

교차 영역 ( cv2.HISTCMP_INTERSECT ):
두 히스토그램에서 각 빈의 최소값을 취해 전체 빈의 합과 비교하는 방식으로, 값이 클수록 유사한 것으로 봅니다.

 

바타차야 거리 ( cv2.HISTCMP_BHATTACHARYYA )
두 확률 분포(정규화된 히스토그램)의 겹침 정도를 평가하는 방법으로, 값이 작으면 유사도가 높음을 나타냅니다.

 

 

각각 cv2에서 제공해주는 함수를 통해 사용할 수 있습니다. 

 

전체코드!

def histScore(image1,image2):
    ## 히스토그램 유사도
    hsv1 = cv2.cvtColor(image1, cv2.COLOR_BGR2HSV)
    hsv2 = cv2.cvtColor(image2, cv2.COLOR_BGR2HSV)

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


    hist_similarity = cv2.compareHist(hist1, hist2, cv2.HISTCMP_CORREL)

    return hist_similarity

(상관계수를 사용해서 비교하였습니다.)

 

 

동일한 사진은 값으로 1을 출력하고 

 

 

색상 히스토그램에 차이가 나면 아래와 같이 값이 감소합니다.

 

 

 

 

 

추가로 특징점을 통해서 비교하는 방법들이 있는데! 

이건 좀 뒤에 실습해 보도록 하겠습니다!

 

 

 

 

 

 

 

 

 


틀린점이 있다면 댓 달아주세요!

728x90

댓글