반응형



이번 포스팅에서는 템플릿 매칭을 사용하여 이미지상에서 오브젝트를 찾는 방법을 다룹니다.





다음 OpenCV Python 튜토리얼을 참고하여 강좌를 비정기적로 포스팅하고 있습니다.


https://docs.opencv.org/4.0.1/d6/d00/tutorial_py_root.html





템플릿 매칭 구현은 다음 링크를 참고하세요.


OpenCV 강좌 - 템플릿 매칭(Template Matching) 구현

https://webnautes.tistory.com/1349




마지막 업데이트  2019. 1. 3




템플릿 매칭은 입력 이미지에서 템플릿 이미지의 위치를 찾는 방법입니다.

OpenCV에서는 템플릿 매칭을 위해 cv.matchTemplate() 함수를 제공합니다.  



2차원 컨볼루션처럼 템플릿 이미지를 입력 이미지상 위에서 이동시키면서 대응하는 픽셀들을 비교합니다.  

OpenCV에서는 다음 여섯가지 비교하는 방법을 제공합니다.




cv.matchTemplate() 함수는 다음 그림의 왼쪽같은 그레이스케일 이미지를 리턴합니다. 그레이 스케일 이미지의 각 픽셀은 템플릿 이미지와 어느 정도 일치한지를 나타냅니다.



입력 이미지의 크기가 W x H이고 템플릿 이미지의 크기가 w x h라면, 결과 이미지의 크기는 (W-w+1, H-h+1)입니다.

결과 이미지를 얻었다면 cv.minMaxLoc() 함수를 사용하여 최대값과 최소값을 찾을 수 있습니다.


cv.minMaxLoc() 함수는  템플릿과 일치하는 사각 영역의 왼쪽 위 코너 위치를 리턴합니다. 사각 영역의 너비와 높이는 템플릿 이미지에서 가져와 사용합니다.


사용하는 방법에 따라 최대값 또는 최소값의 위치를 왼쪽 위 코너 위치로 사용합니다.


  • 최대값 사용

cv.TM_CCOEFF, cv.TM_CCOEFF_NORMED, cv.TM_CCORR, cv.TM_CCORR_NORMED


  • 최소값 사용

cv.TM_SQDIFF, cv.TM_SQDIFF_NORMED



       

                  입력 이미지                  템플릿 이미지



템플릿 매칭 예제 코드입니다. 여섯가지 비교 방법을 사용하여 템플릿 매칭을 진행한 결과를 보여줍니다.


import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt



img = cv.imread('cross.jpg',0)
img2 = img.copy()
template = cv.imread('template.jpg',0)
w, h = template.shape[::-1]


# All the 6 methods for comparison in a list
methods = ['cv.TM_CCOEFF', 'cv.TM_CCOEFF_NORMED', 'cv.TM_CCORR',
           'cv.TM_CCORR_NORMED', 'cv.TM_SQDIFF', 'cv.TM_SQDIFF_NORMED']
for meth in methods:
   img = img2.copy()
   method = eval(meth)


   # Apply template Matching
   res = cv.matchTemplate(img,template,method)
   min_val, max_val, min_loc, max_loc = cv.minMaxLoc(res)
   # If the method is TM_SQDIFF or TM_SQDIFF_NORMED, take minimum
   if method in [cv.TM_SQDIFF, cv.TM_SQDIFF_NORMED]:
       top_left = min_loc
   else:
       top_left = max_loc



   bottom_right = (top_left[0] + w, top_left[1] + h)
   cv.rectangle(img,top_left, bottom_right, 255, 2)


   plt.subplot(121),plt.imshow(res,cmap = 'gray')
   plt.title('Matching Result'), plt.xticks([]), plt.yticks([])
   plt.subplot(122),plt.imshow(img,cmap = 'gray')
   plt.title('Detected Point'), plt.xticks([]), plt.yticks([])
   plt.suptitle(meth)
   plt.show()



여섯가지 비교 방법으로 실행된 템플릿 매칭 결과입니다. 하나의 오브젝트만 찾아 줍니다.  




cv.minMaxLoc() 함수는 값이 최대 또는 최소인 하나의 위치만 알려주기 때문에 하나 이상의 오브젝트를 템플릿 매칭해야 하는 경우에는 사용할 수 없습니다.


이 경우 쓰레쏠드를 사용하면 됩니다.  다음은 다수의 오브젝트를 찾는 예제 코드입니다.


import cv2 as cv
import numpy as np

img_rgb = cv.imread('input.jpg')
img_gray = cv.cvtColor(img_rgb, cv.COLOR_BGR2GRAY)
template = cv.imread('template.jpg', 0)
w, h = template.shape[::-1]

res = cv.matchTemplate(img_gray, template, cv.TM_CCOEFF_NORMED)

threshold = 0.8
loc = np.where(res >= threshold)

for pt in zip(*loc[::-1]):
   cv.rectangle(img_rgb, pt, (pt[0] + w, pt[1] + h), (0, 0, 255), 2)

cv.imshow('result', img_rgb)
cv.waitKey(0)


실행 결과입니다. 템플릿 매칭은 회전된 오브젝트는 검출하지 못합니다.



테스트에 사용한 이미지입니다.


입력 이미지



템플릿 이미지





 

반응형

문제 발생시 지나치지 마시고 댓글 남겨주시면 가능한 빨리 답장드립니다.


제가 쓴 책도 한번 검토해보세요 ^^

+ Recent posts