Notice
Recent Posts
Recent Comments
Link
«   2024/09   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30
Archives
Today
Total
관리 메뉴

NISSO

[OpenCV] Template Matching 본문

Computer Vision

[OpenCV] Template Matching

oniss 2021. 11. 16. 15:42

Template Matching (템플릿 매칭)

object detection의 가장 단순하고 기본적인 형태로, 이미지 내에서 탐지하려는 객체가 포함된 '템플릿' 이미지를 찾는 것이다.

템플릿 이미지를 입력 이미지에서 슬라이딩시켜 전체 이미지에 대해 매칭하면서 두 이미지의 유사도를 계산한다.

이 때 openCV의 cv2.matchTemplate() 함수를 사용한다.

cv2.matchTemplate(image, templ, method, result=None, mask=None)

image : 입력 이미지
templ : 템플릿 이미지
method : 매칭 방법. 이에 따라 유사도 계산 방법이 달라진다.
result : 매칭 결과 행렬. (W - w + 1) * (H - h + 1) 크기의 2차원 array (W,H : image 너비와 높이 / w,h : templ 너비와 높이)
mask : 매칭을 입력 이미지 전체에서 할지, 일부분에서만 할지 결정하는 인자

Template Matching Method

cv2.TM_SQDIFF / cv2.TM_SQDIFF_NORMED

cv2.TM_CCORR / cv2.TM_CCORR_NORMED

cv2.TM_CCOEFF / cv2.TM_CCOEFF_NORMED

총 6개의 매칭 방법이 있다.

TM은 Template Matching의 약자, NORMED가 붙은 방법은 앞의 방법으로 계산한 결과를 [0,1]로 정규화한 것이다.

 

cv2.TM_SQDIFF

cv2.TM_SQDIFF
cv2.TM_SQDIFF_NORMED

SQDIFF : Sum of Squared Difference

cv2.TM_SQDIFF와 cv2.TM_SQDIFF_NORMED는 가장 어두운 곳이 매칭된다. ( 나머지 4개는 가장 밝은 곳이 매칭된다. )

R = { (템플릿 이미지의 픽셀값) - (부분 이미지의 픽셀값) } 의 제곱을 모두 더한 것으로,

완전 일치하면 R = 0(검은색), 유사하지 않으면 R = 255

* 부분 이미지 : 입력 이미지에서 템플릿 이미지와 매칭시킬 위치의 일부분. 템플릿 크기와 같다.

 

 

cv2.TM_CCORR

cv2.TM_CCORR
cv2.TM_CCORR_NORMED

CCORR : Cross Correlation

가장 어두운 곳으로 매칭하는 방법으로, 템플릿 이미지와 부분 이미지의 상관관계를 계산한다.

R = { (템플릿 이미지의 픽셀값) * (입력의 부분 이미지의 픽셀값) } 을 모두 더한 것으로,

완전 일치하면 R = 255, 유사하지 않으면 R = 0

 

 

cv2.TM_CCOEFF

cv2.TM_CCOEFF
cv2.TM_CCOEFF_NORMED

CCOEFF : Correlation Coefficient

가장 어두운 곳으로 매칭하는 방법으로, 밝기를 보정한 cv2.TM_CCORR 방법이다.

R = Σ(T' * I') =  { (템플릿 이미지 - 템플릿 이미지의 평균값) } * { (부분 이미지 - 부분 이미지의 평균값) } 을 더한 것으로,

각 이미지에서 이미지의 평균값을 빼줌으로써 밝기 보정을 할 수 있다.

완전 일치하면 R = 255, 유사하지 않으면 R = 0

cv2.TM_CCOEFF_NORMED : 완전 일치하면 1, 역일치하면 -1, 상호 연관성이 없으면 0

 

Bounding Box

cv2.minMaxLoc(result)

매칭된 유사도의 최소 / 최대값과, 위치의 좌측 상단 꼭지점 좌표를 반환한다.

이 좌표에서 템플릿 이미지의 너비와 높이만큼 box를 치면 매칭된 bounding box가 된다.

min_val, max_val, min_loc, max_loc 로 반환되는데,

cv2.TM_SQDIFF(_NORMED) 방법은 값이 낮을수록 좋은 매칭이므로, min_val과 min_loc을 사용한다.

 

Sample Code

import cv2
import numpy as np

img = cv2.imread('image.jpg')
template = cv2.imread('template.jpg')
h, w = template.shape[:2]

# 모든 매칭 방법 사용
methods = ['cv2.TM_CCOEFF_NORMED', 'cv2.TM_CCOEFF', 'cv2.TM_CCORR_NORMED',
           'cv2.TM_CCORR', 'cv2.TM_SQDIFF_NORMED', 'cv2.TM_SQDIFF']
for method_name in methods:
    img2 = img.copy()
    method = eval(method_name)
    res = cv2.matchTemplate(img, template, method)
    min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(res)

    # TM_SQDIFF : 최소값이 good matching
    if method in [cv2.TM_SQDIFF, cv2.TM_SQDIFF_NORMED]:
        top_left = min_loc
        match_val = min_val
    else:
        top_left = max_loc
        match_val = max_val
        
    # bounding box 표시  
    bottom_right = (top_left[0] + w, top_left[1] + h)
    cv2.rectangle(img_draw, top_left, bottom_right, (0,0,255),2)
    # matching value 표시
    cv2.putText(img2, str(match_val), top_left, cv2.FONT_HERSHEY_PLAIN,2,(0,255,0),1,cv2.LINE_AA)
    cv2.imshow(method_name, img2)
    
cv2.waitKey(0)
cv2.destroyAllWindows()

 

Template Matching의 단점

  • scale(크기)에 민감 : 같은 크기의 sliding window로 템플릿을 매칭시켜가며 찾기 때문에 크기에 민감하다. 템플릿이나 원본 이미지의 크기를 변형시키며 매칭하는 방법으로 해결해야 한다. --> multi scale template matching
  • rotation(회전)에 민감 : 위와 같은 이유로 회전에 민감하다. 이 또한 회전시켜가며 매칭할 수 있지만, 각도가 조금만 다르면 성능이 떨어진다. 

이와 같은 문제점으로, SIFT 알고리즘을 사용해봤다. 

SIFT : Scale Invariant Feature Transform

크기에 불변하는 성질을 가진 특징점 매칭 방법이며, 회전에도 성능이 비교적 잘 나온다.

SIFT에 대해선 다음에 포스팅하도록 하겠다.

 


참고자료

Comments