Maxima's Lab

[Python, Opencv] Template matching (템플릿 매칭) 본문

Python/Opencv

[Python, Opencv] Template matching (템플릿 매칭)

Minima 2022. 6. 14. 20:53
728x90
SMALL

Template matching (템플릿 매칭)

 

오늘은 Template matching을 통해 Original Image 내 Template Image와 유사(일치)한 영역을 찾는 알고리즘입니다.

위의 알고리즘을 적용하기 위해 필요한 사항들은 다음과 같습니다. 

※ opencv의 cv2.matchTemplate(), cv2.minMaxLoc() 함수 사용 

 

  1. Original Image (원본 이미지)
  2. Template Image (템플릿 이미지)
  3. Template matching 방법

 

위의 3가지 사항을 적용하기 이전, cv2.minMaxLoc() 함수에 대해서 알아보겠습니다.

 

  • cv2.minMaxLoc() : array에서 global minimum(전역 최소값)과 global maximum(전역 최대값)을 구하는 함수
import numpy as np
import cv2

arr = np.array([1, -2, 0, 7])
cv2.minMaxLoc(arr)

Output : (-2.0, 7.0, (0, 1), (0, 3))

 

결과값을 Tuple의 형태로 반환하며,  이는 (최소값, 최대값, 최소값의 위치, 최대값의 위치)를 의미합니다.

1-D array의 경우임에도 불구하고 (x, y)의 형태로 위치값을 반환합니다. (단, x=0)

 

2-D array의 경우는 다음과 같습니다.

 

import numpy as np
import cv2

arr = np.array([[-5, 2, 3, 10],
               [6, 11, -2, 5]])
cv2.minMaxLoc(arr)

Output : (-5.0, 11.0, (0, 0), (1, 1))

 

※cv2.minMaxLoc() 함수는 단일 채널(single channel)인 경우에만 적용 가능합니다.

 

  • cv2.matchTemplate() 을 적용하기 위해 6가지 방법들에 대해서 알아보겠습니다.
print(eval('cv2.TM_SQDIFF')) # 0
print(eval('cv2.TM_SQDIFF_NORMED')) # 1
print(eval('cv2.TM_CCORR')) # 2
print(eval('cv2.TM_CCORR_NORMED')) # 3
print(eval('cv2.TM_CCOEFF')) # 4
print(eval('cv2.TM_CCOEFF_NORMED')) # 5

 

총 6가지 방법들에 대해 순서대로 0, 1, 2, ... , 5 의 정수형을 반환합니다. 

  • Original Image --> (H, W, C) or (H, w)
  • Template Image --> (H_t, W_t, C_t) or (H_t, W_t)
  • cv2.matchTemplate(Original Image, Template Image, method_value) --> (H - H_t + 1, W - W_t + 1)

 

Original Image
Template Image

1.  Grayscale Image를 이용한 Template matching

import matplotlib.pyplot as plt
import cv2

original_img = cv2.imread("...") # (H, W, C)
template_img = cv2.imread("...") # (H_t, W_t, C_t)

H_t, W_t, _ = template_img.shape

method_index_list = list(range(0, 6)) # [0, 1, 2, 3, 4, 5, 6]
method_list = ['cv2.TM_SQDIFF', 'cv2.TM_SQDIFF_NORMED', 'cv2.TM_CCORR', 'cv2.TM_CCORR_NORMED', 'cv2.TM_CCOEFF', 'cv2.TM_CCOEFF_NORMED']

for method_index in method_index_list:
	
    original_img_temp = original_img.copy()
    
    ####### Convert BGR Image to Grayscale Image #######
    original_gray = cv2.cvtColor(original_img, cv2.COLOR_BGR2GRAY).copy()
    template_gray = cv2.cvtColor(template_img, cv2.COLOR_BGR2GRAY).copy()

    
    result_img = cv2.matchTemplate(original_gray, template_gray, method_index)
    
    min_value, max_value, min_location, max_location = cv2.minMaxLoc(result_img)
    
    if method_index in [0, 1]: # 'cv2.TM_SQDIFF', 'cv2.TM_SQDIFF_NORMED'
    	Top_L = min_location
        
    else:
    	Top_L = max_location
        
    Bottom_R = (Top_L[0] + W_t-1, Top_L[1] + H_t-1)
    

    cv2.rectangle(original_img_temp, Top_L, Bottom_R, (255, 255, 255), 5)
    
    plt.title("Result Of Template Matching ({})".format(method_list[method_index]))
    plt.imshow(original_img_temp)
    plt.show()

Template matching 알고리즘 적용을 위해 Original Image와 Template Image를 Grayscale로 변환 후 cv2.matchTemplate() 함수를 적용하였습니다. 이어서 Blue-channel Image를 활용하여 Template matching을 적용해보겠습니다.

2.  Blue-channel Image를 이용한 Template matching

import matplotlib.pyplot as plt
import cv2

original_img = cv2.imread("...") # (H, W, C)
template_img = cv2.imread("...") # (H_t, W_t, C_t)

H_t, W_t, _ = template_img.shape

method_index_list = list(range(0, 6)) # [0, 1, 2, 3, 4, 5, 6]
method_list = ['cv2.TM_SQDIFF', 'cv2.TM_SQDIFF_NORMED', 'cv2.TM_CCORR', 'cv2.TM_CCORR_NORMED', 'cv2.TM_CCOEFF', 'cv2.TM_CCOEFF_NORMED']

for method_index in method_index_list:
	
    original_img_temp = original_img.copy()
    
    ####### Blue-Channel Image #######
    original_blue = original_img.copy()[:,:,0]
    template_blue = template_img.copy()[:,:,0]

    
    result_img = cv2.matchTemplate(original_blue, template_blue, method_index)
    
    min_value, max_value, min_location, max_location = cv2.minMaxLoc(result_img)
    
    if method_index in [0, 1]: # 'cv2.TM_SQDIFF', 'cv2.TM_SQDIFF_NORMED'
    	Top_L = min_location
        
    else:
    	Top_L = max_location
        
    Bottom_R = (Top_L[0] + W_t-1, Top_L[1] + H_t-1)
    

    cv2.rectangle(original_img_temp, Top_L, Bottom_R, (255, 255, 255), 5)
    
    plt.title("Result Of Template Matching ({})".format(method_list[method_index]))
    plt.imshow(original_img_temp)
    plt.show()

기존 Grayscale 변환하였던 위치에서 Blue-channel Image로 수정해주시면 됩니다. 위의 방법과 마찬가지로 Green, Red-channel 및 다른 색상 공간에 대해서도 적용해보시기 바랍니다.

728x90
LIST
Comments