๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ

AI/Computer Vision

[Computer Vision] ์ด๋ฏธ์ง€ ์œ ์‚ฌ๋„

728x90
๋ฐ˜์‘ํ˜•
๐Ÿ‘€ ๋ณธ ์˜ˆ์ œ๋Š” Window10์˜ VSCode, Python3.11.0๋กœ ์ž‘์„ฑ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

 

์ด๋ฏธ์ง€ ์œ ์‚ฌ๋„๋Š” ๋‘ ์ด๋ฏธ์ง€ ๊ฐ„์˜ ์œ ์‚ฌ์„ฑ์„ ํ‰๊ฐ€ํ•˜๋Š” ๊ฐœ๋…์œผ๋กœ, ์ฃผ๋กœ ์ปดํ“จํ„ฐ ๋น„์ „ ๋ฐ ์ด๋ฏธ์ง€ ์ฒ˜๋ฆฌ ๋ถ„์•ผ์—์„œ ์‚ฌ์šฉ๋œ๋‹ค.

 

์ด๋ฏธ์ง€ ์œ ์‚ฌ๋„์˜ ์ธก์ • ๋ฐฉ๋ฒ•์€ ์—ฌ๋Ÿฌ ๊ฐ€์ง€๊ฐ€ ์žˆ์œผ๋ฉฐ, ๊ฐ ๋ฐฉ๋ฒ•์€ ํŠน์ •ํ•œ ๊ธฐ์ค€์ด๋‚˜ ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•œ๋‹ค.

 

์ด๋ฏธ์ง€ ์œ ์‚ฌ๋„๋ฅผ ํ‰๊ฐ€ํ•˜๋Š” ์ด์œ ๋Š” ๋‹ค์–‘ํ•˜๋‚˜ ์ผ๋ฐ˜์ ์œผ๋กœ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋ชฉ์ ์„ ๊ฐ€์ง€๊ณ  ์žˆ๋‹ค.

  • ๊ฒ€์ƒ‰ ๋ฐ ์ถ”์ฒœ ์‹œ์Šคํ…œ : ์ด๋ฏธ์ง€ ๊ฒ€์ƒ‰ ์—”์ง„, ์ถ”์ฒœ์— ์‚ฌ์šฉ๋˜์–ด ์‚ฌ์šฉ์ž๊ฐ€ ์ž…๋ ฅํ•œ ์ด๋ฏธ์ง€์™€ ์œ ์‚ฌํ•œ ์ด๋ฏธ์ง€๋ฅผ ์ฐพ๋Š”๋ฐ ๋„์›€์„ ์ค€๋‹ค.
  • ์ค‘๋ณต ์ด๋ฏธ์ง€ ํƒ์ง€ : ์›น ์‚ฌ์ดํŠธ๋‚˜ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค์—์„œ ์ค‘๋ณต๋œ ์ด๋ฏธ์ง€๋ฅผ ์ฐพ์•„๋‚ด๊ธฐ ์œ„ํ•ด ์œ ์‚ฌ๋„ ์ธก์ •์ด ํ•„์š”ํ•˜๋‹ค.
  • ์ด๋ฏธ์ง€ ํ’ˆ์งˆ ํ‰๊ฐ€ : ์ด๋ฏธ์ง€์˜ ํ’ˆ์งˆ์„ ํ‰๊ฐ€ํ•˜๊ฑฐ๋‚˜, ์••์ถ• ํ›„์˜ ์ด๋ฏธ์ง€๊ฐ€ ์›๋ณธ๊ณผ ์–ผ๋งˆ๋‚˜ ์œ ์‚ฌํ•œ์ง€๋ฅผ ํŒ๋‹จํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋œ๋‹ค.
  • ๊ฐ์ฒด ์ธ์‹ ๋ฐ ๋ถ„๋ฅ˜ : ์ด๋ฏธ์ง€ ๋‚ด์˜ ๊ฐ์ฒด๋ฅผ ์ธ์‹ํ•˜๊ณ  ๋ถ„๋ฅ˜ํ•˜๋Š” ๊ณผ์ •์—์„œ๋„ ์œ ์‚ฌ๋„ ์ธก์ •์ด ์ค‘์š”ํ•œ ์—ญํ• ์„ ํ•œ๋‹ค.

 

ํ”ฝ์…€ ๊ธฐ๋ฐ˜ ์œ ์‚ฌ๋„ ์ธก์ • - MSE(Mean Squared Error)

๋‘ ์ด๋ฏธ์ง€์˜ ๊ฐ ํ”ฝ์…€ ๊ฐ’ ๊ฐ„์˜ ์ฐจ์ด๋ฅผ ์ œ๊ณฑํ•˜์—ฌ ํ‰๊ท ์„ ๊ตฌํ•˜๋Š” ๋ฐฉ๋ฒ•์ด๋‹ค.

 

๋‘ ์ด๋ฏธ์ง€ ๊ฐ„์˜ ์ฐจ์ด๋ฅผ ์ •๋Ÿ‰์ ์œผ๋กœ ํ‰๊ฐ€ํ•  ๋•Œ ์‚ฌ์šฉ๋œ๋‹ค.

๊ฐ’์€ 0 ์ด์ƒ์ด๋ฉฐ, 0์— ๊ฐ€๊นŒ์šธ์ˆ˜๋ก ๋‘ ์ด๋ฏธ์ง€๊ฐ€ ์œ ์‚ฌํ•˜๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•œ๋‹ค.

 

MSE๋Š” ์ด๋ฏธ์ง€์˜ ๊ตฌ์กฐ์  ์ •๋ณด๋‚˜ ์ธ๊ฐ„์˜ ์‹œ๊ฐ์  ์ธ์‹์„ ๋ฐ˜์˜ํ•˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์—, ๋‘ ์ด๋ฏธ์ง€๊ฐ€ ์‹œ๊ฐ์ ์œผ๋กœ ์œ ์‚ฌํ•˜๋”๋ผ๋„ MSE๊ฐ’์ด ๋†’๊ฒŒ ๋‚˜์˜ฌ ์ˆ˜ ์žˆ๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด, ์ด๋ฏธ์ง€์˜ ๋ฐ๊ธฐ๋‚˜ ๋Œ€๋น„๊ฐ€ ๋‹ค๋ฅผ ๊ฒฝ์œ  MSE๋Š” ํฐ ๊ฐ’์„ ๊ฐ€์งˆ ์ˆ˜ ์žˆ๋‹ค.

 

๋‹ค๋ฅธ ๋ฐฉ๋ฒ•๋“ค๊ณผ ํ•จ๊ป˜ ์‚ฌ์šฉ๋˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋งŽ๋‹ค.

import cv2
import numpy as np
from numba import jit


@jit
def mse(imageA:np.ndarray, imageB:np.ndarray):
    # ๋‘ ์ด๋ฏธ์ง€์˜ ์ฐจ์ด๋ฅผ ๊ณ„์‚ฐ
    err = np.sum((imageA.astype("float") - imageB.astype("float")) ** 2)
    err /= float(imageA.shape[0] * imageA.shape[1])
    return err


if __name__ == "__main__":
    im1 = cv2.imread("cat1.jpg")
    im2 = cv2.imread("cat1.jpg")
    ratio = mse(im1,im2)
    print(f"์œ ์‚ฌ๋„ : {ratio}")

๊ฐ™์€ ์ด๋ฏธ์ง€ ์ผ๋•Œ๋Š” 0์ด๋‹ค.

 

ํ•˜์ง€๋งŒ ๋‹ค๋ฅธ ์ด๋ฏธ์ง€์˜ ๊ฒฝ์šฐ 0๋ณด๋‹ค ํฐ ๊ฐ’์ด ๋‚˜์˜จ๋‹ค.

 

 

MSE ๋ฐฉ๋ฒ•์€ ์•ž์„œ ๋งํ–ˆ๋“ฏ ์‚ฌ๋žŒ์˜ ์‹œ๊ฐ์  ์ธ์‹์„ ๋ฐ˜์˜ํ•˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— ๊ฐœ์™€ ๊ณ ์–‘์ด๋ฅผ ๊ตฌ๋ถ„ํ•˜์ง€ ๋ชปํ•œ๋‹ค.

๊ทธ๋ฆฌ๊ณ  ๊ฐ™์€ ๊ณ ์–‘์ด ์ด๋ฏธ์ง€๋”๋ผ๋„ ์•„์˜ˆ ๋‹ค๋ฅธ ์ด๋ฏธ์ง€๋กœ ์ธ์‹ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋‹จ๋…์ ์œผ๋กœ ์‚ฌ์šฉํ•˜๊ธฐ ํž˜๋“ค๋‹ค.

 

 

ํ”ฝ์…€ ๊ธฐ๋ฐ˜ ๋ฐฉ๋ฒ• - PSNR(Peak Signal-to-Noise Ratio)

MSE๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•˜์—ฌ ์‹ ํ˜ธ ๋Œ€ ์žก์Œ ๋น„์œจ์„ ๊ณ„์‚ฐํ•œ๋‹ค.

 

์ฃผ๋กœ ์••์ถ•๋œ ์ด๋ฏธ์ง€์™€ ์›๋ณธ ์ด๋ฏธ์ง€ ๊ฐ„์˜ ํ’ˆ์งˆ์„ ๋น„๊ตํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋œ๋‹ค.

๊ฐ’์ด ๋†’์„์ˆ˜๋ก ๋‘ ์ด๋ฏธ์ง€ ๊ฐ„์˜ ์œ ์‚ฌ์„ฑ์ด ๋†’๊ณ  ํ’ˆ์งˆ์ด ์ข‹๋‹ค๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•œ๋‹ค.

 

import cv2
import numpy as np
from numba import jit
from copy import copy

def mse(imageA, imageB):
    # ๋‘ ์ด๋ฏธ์ง€์˜ ์ฐจ์ด๋ฅผ ๊ณ„์‚ฐ
    err = np.sum((imageA.astype("float") - imageB.astype("float")) ** 2)
    err /= float(imageA.shape[0] * imageA.shape[1])
    return err

def psnr(imageA, imageB):
    # MSE ๊ณ„์‚ฐ
    error = mse(imageA, imageB)
    if error == 0:
        return float('inf')  # ๋‘ ์ด๋ฏธ์ง€๊ฐ€ ๋™์ผํ•  ๊ฒฝ์šฐ PSNR์€ ๋ฌดํ•œ๋Œ€
    MAX_PIXEL_VALUE = 255.0  # 8๋น„ํŠธ ์ด๋ฏธ์ง€์˜ ์ตœ๋Œ€ ํ”ฝ์…€ ๊ฐ’
    return 10 * np.log10((MAX_PIXEL_VALUE ** 2) / error)

if __name__ == "__main__":
    im = cv2.imread("cat1.jpg")
    zim = copy(im) # ์ €ํ™”์งˆ ์ด๋ฏธ์ง€
    zim = cv2.blur(zim,(5,5))

    psnr_ori = psnr(im,zim)

    print(f"k(5,5) ์œ ์‚ฌ๋„: {psnr_ori} dB")
    
    zim = cv2.blur(zim,(9,9))
    psnr_val = psnr(im,zim)
    
    print(f"k(9,9) ์œ ์‚ฌ๋„ : {psnr_val} dB")

    cv2.imshow("img",im)
    cv2.imshow("low img",zim)

    cv2.waitKey(0)
    cv2.destroyAllWindows()

 

์ด๋ฏธ์ง€ ํ™”์งˆ์ด ๋” ๋–จ์–ด์งˆ ์ˆ˜๋ก ๋” ๊ฐ’์ด ๋‚ฎ์•„์ง„๋‹ค.

 

 

๊ตฌ์กฐ ๊ธฐ๋ฐ˜ ๋ฐฉ๋ฒ• - SSIM(Structural Similarity Index)

SSIM์€ ๋‘ ์ด๋ฏธ์ง€ ๊ฐ„์˜ ๊ตฌ์กฐ์  ์œ ์‚ฌ์„ฑ์„ ์ธก์ •ํ•˜๋Š” ์ง€ํ‘œ๋กœ, ์ด๋ฏธ์ง€ ํ’ˆ์งˆ ํ‰๊ฐ€์— ๋„๋ฆฌ ์‚ฌ์šฉ๋œ๋‹ค.

๋ฐ๊ธฐ, ๋Œ€๋น„, ๊ตฌ์กฐ์˜ ์„ธ ๊ฐ€์ง€ ์š”์†Œ๋ฅผ ๊ณ ๋ คํ•˜์—ฌ ๋‘ ์ด๋ฏธ์ง€์˜ ์œ ์‚ฌ์„ฑ์„ ํ‰๊ฐ€ํ•œ๋‹ค.

 

๊ฐ’์€ 0~1 ์‚ฌ์ด์˜ ๊ฐ’์„ ๊ฐ€์ง€๊ณ  1์— ๊ฐ€๊นŒ์šธ์ˆ˜๋ก ๋‘ ์ด๋ฏธ์ง€๊ฐ€ ์œ ์‚ฌํ•˜๋‹ค๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•œ๋‹ค.

import cv2
from skimage.metrics import structural_similarity as ssim

# ์ด๋ฏธ์ง€ ์ฝ๊ธฐ
imageA = cv2.imread('cat1.jpg')
cv2.imshow("im1",imageA)
imageB = cv2.imread('cat2.jpg')
cv2.imshow("im2",imageB)

# ์ด๋ฏธ์ง€๋ฅผ ๊ทธ๋ ˆ์ด์Šค์ผ€์ผ๋กœ ๋ณ€ํ™˜ (SSIM ๊ณ„์‚ฐ์„ ์œ„ํ•ด)
imageA_gray = cv2.cvtColor(imageA, cv2.COLOR_BGR2GRAY)
imageB_gray = cv2.cvtColor(imageB, cv2.COLOR_BGR2GRAY)

# SSIM ๊ณ„์‚ฐ
ssim_index, _ = ssim(imageA_gray, imageB_gray, full=True)

print(f'SSIM: {ssim_index}')

cv2.waitKey(0)
cv2.destroyAllWindows()

 

์ด๋ฏธ์ง€์˜ ๊ตฌ์กฐ, ๋ฐ๊ธฐ, ๋Œ€๋น„ ๋“ฑ์„ ํ†ตํ•ด ์œ ์‚ฌ๋„๋ฅผ ํ‰๊ฐ€ํ•˜๋ฏ€๋กœ ๋‹ค๋ฅธ ์ด๋ฏธ์ง€์ธ์ง€๋Š” ํ‰๊ฐ€ ๊ฐ€๋Šฅํ•˜๋‚˜ ๊ณ ์–‘์ด, ๊ฐ•์•„์ง€, ํ† ๋ผ ์ด๋ ‡๊ฒŒ ๊ตฌ๋ถ„์€ ํ•  ์ˆ˜ ์—†๋‹ค.

 

ํŠน์ง• ๊ธฐ๋ฐ˜ ๋ฐฉ๋ฒ• - SIFT(Scale-Invariant Feature Transform)

์ด๋ฏธ์ง€์˜ ํŠน์ง•์ ์„ ์ถ”์ถœํ•˜๊ณ  ์ด๋ฏธ์ง€ ๊ฐ„์˜ ๋งค์นญ์„ ์ˆ˜ํ–‰ํ•˜๋Š” ์•Œ๊ณ ๋ฆฌ์ฆ˜์œผ๋กœ ๋‹ค์–‘ํ•œ ์Šค์ผ€์ผ๊ณผ ํšŒ์ „, ์กฐ๋ช… ๋ณ€ํ™”์— ๊ฐ•์ธํ•œ ํŠน์ง•์„ ์ œ๊ณตํ•˜์—ฌ ์ปดํ“จํ„ฐ ๋น„์ „ ๋ถ„์•ผ์— ๋„๋ฆฌ ์‚ฌ์šฉ๋œ๋‹ค.

 

์ฃผ์š” ๋‹จ๊ณ„

  • ์Šค์ผ€์ผ ๊ณต๊ฐ„ ๊ทน๋Œ€ํ™”
  • ํŠน์ง•์  ๋กœ์ปฌ๋ผ์ด์ œ์ด์…˜
  • ์ฃผ ๋ฐฉํ–ฅ ํ• ๋‹น
  • ํŠน์ง• ๋ฒกํ„ฐ ์ƒ์„ฑ
  • ํŠน์ง•์  ๋งค์นญ

 

 

์žฅ์ 

  • ์Šค์ผ€์ผ ๋ถˆ๋ณ€
  • ํšŒ์ „ ๋ถˆ๋ณ€
  • ์กฐ๋ช… ๋ณ€ํ™”์— ๊ฐ•์ธ

 

๋‹จ์ 

  • ๊ณ„์‚ฐ ๋น„์šฉ์ด ๋งŽ์ด ๋“ ๋‹ค.

 

 

import cv2

# ์ด๋ฏธ์ง€ ์ฝ๊ธฐ
image1 = cv2.imread('cat1.jpg', cv2.IMREAD_GRAYSCALE)
image2 = cv2.imread('cat2.jpg', cv2.IMREAD_GRAYSCALE)

# SIFT ๊ฐ์ฒด ์ƒ์„ฑ
sift = cv2.SIFT_create()

# ํŠน์ง•์  ๋ฐ ๋””์Šคํฌ๋ฆฝํ„ฐ ์ถ”์ถœ
keypoints1, descriptors1 = sift.detectAndCompute(image1, None)
keypoints2, descriptors2 = sift.detectAndCompute(image2, None)

# ๋งค์นญ์„ ์œ„ํ•œ BFMatcher ์ƒ์„ฑ
bf = cv2.BFMatcher(cv2.NORM_L2, crossCheck=True)

# ํŠน์ง•์  ๋งค์นญ
matches = bf.match(descriptors1, descriptors2)

# ๋งค์นญ ๊ฒฐ๊ณผ ์ •๋ ฌ
matches = sorted(matches, key=lambda x: x.distance)

# ๋งค์นญ ๊ฒฐ๊ณผ ์‹œ๊ฐํ™”
result_image = cv2.drawMatches(image1, keypoints1, image2, keypoints2, matches, None)

print(f"NUmber of match result : {len(matches)}/{len(descriptors1)}")

# ๊ฒฐ๊ณผ ์ด๋ฏธ์ง€ ์ถœ๋ ฅ
cv2.imshow('SIFT Matches', result_image)
cv2.waitKey(0)
cv2.destroyAllWindows()

 

์ด ๋ฐฉ๋ฒ•๋„ cat, dog, rabbit์„ ๊ตฌ๋ถ„ํ•˜์ง€๋Š” ๋ชปํ•œ๋‹ค.

 

ํŠน์ง• ๊ธฐ๋ฐ˜ ๋ฐฉ๋ฒ• - SURF(Speeded-Up Robust Features)

์ด๋ฏธ์ง€์˜ ํŠน์ง•์ ์„ ์ถ”์ถœํ•˜์—ฌ ์ด๋ฏธ์ง€๋ฅผ ๋งค์นญํ•˜๋Š” ์•Œ๊ณ ๋ฆฌ์ฆ˜์œผ๋กœ SIFT์˜ ๋Œ€์•ˆ์œผ๋กœ ๊ฐœ๋ฐœ๋˜์—ˆ์œผ๋ฏ€๋กœ ๋” ๋น ๋ฅด๊ณ  ํšจ์œจ์ ์ธ ํŠน์ง•์  ์ถ”์ถœ์„ ๋ชฉํ‘œ๋กœํ•œ๋‹ค.

 

import cv2
import numpy as np

# ์ด๋ฏธ์ง€ ๋กœ๋“œ
img1 = cv2.imread('cat1.jpg', cv2.IMREAD_GRAYSCALE)  # ์ฒซ ๋ฒˆ์งธ ์ด๋ฏธ์ง€
img2 = cv2.imread('cat2.jpg', cv2.IMREAD_GRAYSCALE)  # ๋‘ ๋ฒˆ์งธ ์ด๋ฏธ์ง€

# SURF ๊ฐ์ฒด ์ƒ์„ฑ
surf = cv2.xfeatures2d.SURF_create(hessianThreshold=400)

# ํŠน์ง•์  ๊ฒ€์ถœ ๋ฐ ๊ธฐ์ˆ ์ž ์ƒ์„ฑ
keypoints1, descriptors1 = surf.detectAndCompute(img1, None)
keypoints2, descriptors2 = surf.detectAndCompute(img2, None)

# ๋งค์นญ์„ ์œ„ํ•œ BFMatcher ๊ฐ์ฒด ์ƒ์„ฑ
bf = cv2.BFMatcher(cv2.NORM_L2, crossCheck=True)

# ํŠน์ง•์  ๋งค์นญ
matches = bf.match(descriptors1, descriptors2)

# ๋งค์นญ ๊ฒฐ๊ณผ๋ฅผ ๊ฑฐ๋ฆฌ ๊ธฐ์ค€์œผ๋กœ ์ •๋ ฌ
matches = sorted(matches, key=lambda x: x.distance)

# ๋งค์นญ ๊ฒฐ๊ณผ ์‹œ๊ฐํ™”
img_matches = cv2.drawMatches(img1, keypoints1, img2, keypoints2, matches, None, flags=cv2.DrawMatchesFlags_NOT_DRAW_SINGLE_POINTS)

print(f"NUmber of match result : {len(matches)}/{len(descriptors1)}")
# ๊ฒฐ๊ณผ ์ด๋ฏธ์ง€ ํ‘œ์‹œ
cv2.imshow('Matches', img_matches)
cv2.waitKey(0)
cv2.destroyAllWindows()

 

OpenCV 3.4.2 ์ด์ƒ์—์„œ๋Š” ์ €์ž‘๊ถŒ์œผ๋กœ ๋ณดํ˜ธ๋˜๊ธฐ ๋•Œ๋ฌธ์— CMake ์˜ต์…˜์„ ํ™œ์„ฑํ™”ํ•ด์„œ OpenCV๋ฅผ ๋น„๊ณต์‹์ ์œผ๋กœ ์‚ฌ์šฉํ•ด์•ผํ•œ๋‹ค.

 

 

๋ฒกํ„ฐ ๊ณต๊ฐ„ - Cosine Similarity, Hamming Distance

Cosine Similarity๋Š” ๋‘ ๋ฒกํ„ฐ ๊ฐ„์˜ ์ฝ”์‚ฌ์ธ ๊ฐ๋„๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ์œ ์‚ฌ์„ฑ์„ ์ธก์ •ํ•˜๊ณ  ๋‘ ๋ฒกํ„ฐ๊ฐ€ ์–ผ๋งˆ๋‚˜ ์œ ์‚ฌํ•œ์ง€๋ฅผ 0๊ณผ 1 ์‚ฌ์ด์˜ ๊ฐ’์œผ๋กœ ๋‚˜ํƒ€๋‚ด๋ฉฐ, 1์— ๊ฐ€๊นŒ์šธ์ˆ˜๋ก ์œ ์‚ฌ์„ฑ์ด ๋†’๊ณ , 0์— ๊ฐ€๊นŒ์šธ์ˆ˜๋ก ์œ ์‚ฌ์„ฑ์ด ๋‚ฎ๋‹ค.

  • ์ฃผ๋กœ ์ด์ง„ ๋ฐ์ดํ„ฐ๋‚˜ ๋ฌธ์ž์—ด์˜ ์œ ์‚ฌ์„ฑ์„ ์ธก์ •ํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋œ๋‹ค.
  • ๋‘ ๋ฒกํ„ฐ์˜ ๊ธธ์ด๊ฐ€ ๊ฐ™์•„์•ผ ํ•˜๋ฉฐ, ์„œ๋กœ ๋‹ค๋ฅธ ์œ„์น˜์˜ ์š”์†Œ ์ˆ˜๋ฅผ ์„ธ๋Š” ๋ฐฉ์‹์ด๋‹ค.
  • ๋ฒกํ„ฐ์˜ ๋ฐฉํ–ฅ์„ ๊ธฐ๋ฐ˜์œผ๋กœ ์œ ์‚ฌ์„ฑ์„ ์ธก์ •ํ•œ๋‹ค.
import numpy as np
from sklearn.metrics.pairwise import cosine_similarity
from PIL import Image

def image_to_vector(image_path):
    image = Image.open(image_path).convert('L')  # ํ‘๋ฐฑ ์ด๋ฏธ์ง€๋กœ ๋ณ€ํ™˜
    image = image.resize((100, 100))  # ํฌ๊ธฐ ์กฐ์ •
    return np.array(image).flatten()  # 1์ฐจ์› ๋ฐฐ์—ด๋กœ ๋ณ€ํ™˜

# ์ด๋ฏธ์ง€ ๊ฒฝ๋กœ
image1_path = 'cat1.jpg'
# image2_path = 'cat2.jpg'
image2_path = 'dog1.jpg'

# ์ด๋ฏธ์ง€ ๋ฒกํ„ฐํ™”
vector1 = image_to_vector(image1_path)
vector2 = image_to_vector(image2_path)

# ์ฝ”์‚ฌ์ธ ์œ ์‚ฌ๋„ ๊ณ„์‚ฐ
similarity = cosine_similarity([vector1], [vector2])
print(f"Cosine Similarity: {similarity[0][0]}")

 

 

Hamming Distance๋Š” ๋‘ ๋ฌธ์ž์—ด ๋˜๋Š” ์ด์ง„๋ฒกํ„ฐ ๊ฐ„์˜ ์ฐจ์ด๋ฅผ ์ธก์ •ํ•˜๋Š” ๋ฐฉ๋ฒ•์ด๋‹ค. ๋‘ ๋ฒกํ„ฐ์˜ ๊ธธ์ด๊ฐ€ ๊ฐ™์„ ๋•Œ, ์„œ๋กœ ๋‹ค๋ฅธ ์œ„์น˜์˜ ์š”์†Œ ์ˆ˜๋ฅผ ๊ณ„์‚ฐํ•˜์—ฌ ๊ฑฐ๋ฆฌ๋ฅผ ์ •์˜ํ•œ๋‹ค.

  • ์ฃผ๋กœ ์ด์ง„ ๋ฐ์ดํ„ฐ๋‚˜ ๋ฌธ์ž์—ด์˜ ์œ ์‚ฌ์„ฑ์„ ์ธก์ •ํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋œ๋‹ค.
  • ๋‘ ๋ฒกํ„ฐ์˜ ๊ธธ์ด๊ฐ€ ๊ฐ™์•„์•ผ ํ•˜๋ฉฐ, ์„œ๋กœ ๋‹ค๋ฅธ ์œ„์น˜์˜ ์š”์†Œ ์ˆ˜๋ฅผ ์„ธ๋Š” ๋ฐฉ์‹์ด๋‹ค.
  • ๋‘ ๋ฒกํ„ฐ์˜ ์ฐจ์ด๋ฅผ ์ธก์ •ํ•œ๋‹ค.
import numpy as np
from PIL import Image

def image_to_binary_vector(image_path):
    image = Image.open(image_path).convert('1')  # ์ด์ง„ ์ด๋ฏธ์ง€๋กœ ๋ณ€ํ™˜
    return np.array(image).flatten()  # 1์ฐจ์› ๋ฐฐ์—ด๋กœ ๋ณ€ํ™˜

# ์ด๋ฏธ์ง€ ๊ฒฝ๋กœ
image1_path = 'cat1.jpg'
image2_path = 'dog1.jpg'

# ์ด์ง„ ์ด๋ฏธ์ง€ ๋ฒกํ„ฐํ™”
binary_vector1 = image_to_binary_vector(image1_path)
binary_vector2 = image_to_binary_vector(image2_path)

# ํ•ด๋ฐ ๊ฑฐ๋ฆฌ ๊ณ„์‚ฐ
def hamming_distance(A, B):
    if len(A) != len(B):
        raise ValueError("๋‘ ๋ฒกํ„ฐ์˜ ๊ธธ์ด๋Š” ๊ฐ™์•„์•ผ ํ•ฉ๋‹ˆ๋‹ค.")
    return np.sum(A != B)

distance = hamming_distance(binary_vector1, binary_vector2)
print(f"Hamming Distance: {distance}")

 

 

ํ•˜์ง€๋งŒ ์ด ๋ฐฉ๋ฒ•๋“ค์€ ์ œ๋Œ€๋กœ๋œ ๋น„๊ต๋ฅผ ํ•˜๊ธฐ ํž˜๋“ค๋‹ค. ์ด๋ฏธ์ง€ ๋ถ„๋ฅ˜, ๋ฒกํ„ฐ DB ๊ตฌ์ถ• ๋“ฑ์„ ์ด๋ฏธ์ง€ ์œ ์‚ฌ๋„๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํ•˜๋ ค๋ฉด ์ด๋ฏธ์ง€๋ฅผ ๋ฒกํ„ฐํ™”ํ•˜๋Š” ์ž„๋ฒ ๋”ฉ ๋ชจ๋ธ์„ ์‚ฌ์šฉํ•˜์—ฌ ๋ฒกํ„ฐํ™”ํ•ด์•ผ ํ•œ๋‹ค.

 

 

 

AI๋ฅผ ์‚ฌ์šฉ

CNN๊ณผ ๊ฐ™์€ ๋ชจ๋ธ๋กœ ์ด๋ฏธ์ง€๋ฅผ ํŠน์ง• ๋ฒกํ„ฐ๋กœ ๋ณ€ํ™˜ ํ›„, ์ด๋ฏธ์ง€ ๋ฒกํ„ฐ๋“ค ๊ฐ„์˜ ์œ ์‚ฌ๋„๋ฅผ ๊ณ„์‚ฐํ•œ๋‹ค.

๋Œ€ํ‘œ์ ์œผ๋กœ Siamese Network, Pre-trained CNN ๋“ฑ์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

728x90
๋ฐ˜์‘ํ˜•

'AI > Computer Vision' ์นดํ…Œ๊ณ ๋ฆฌ์˜ ๋‹ค๋ฅธ ๊ธ€

[Computer Vision] Skeletonization  (0) 2024.09.20
[Computer Vision] Segmentation  (0) 2024.09.19
[Computer Vision] Depth  (0) 2024.09.15
[Computer Vision] Trapped-ball Segmentation  (0) 2024.09.14
[Computer Vision] IoU(Intersection over Union)  (0) 2024.09.12