Python/파이썬 OpenCV 공부

[파이썬 OpenCV] 탬플릿 매칭으로 원하는 영상 찾기 - cv2.matchTemplate

AI 꿈나무 2020. 10. 13. 21:53
반응형

탬플릿 매칭 - Template matching

 템플릿 매칭은 입력 영상에서 (작은 크기의) 템플릿 영상과 일치하는 부분을 찾는 기법입니다.

 템플릿은 찻을 대상이 되는 작은 영상을 의미합니다. 커널이라는 용어도 씁니다.

 

템플릿
메시 얼굴 검출

 

 탬플릿 매칭은 노이즈와 밝기 변화에 강합니다.

 CCOFF 연산을 이용하면 밝기 보정을 해서 매칭하기 때문입니다.

 가우시안 노이즈 경우에 correlation 방법이 잘 동작합니다.

 

 다만 기본적으로 같은 위치에 있는 픽셀 값들을 곱하고 더해서 유사도를 판단하는 방식이기 때문에 회전, 크기변환이 심하게 일어난 경우 내가 찾고자하는 템플릿 영상의 위치를 제대로 찾을 수 없습니다.

 다른 방법을 이용해야 하는데 키포인트 로칼 피쳐매칭, 로칼 피쳐 포인트 매칭을 생각해볼 수 있습니다.

 

1. 템플릿 동작 방식

 필터링에서 동작하던 방식이랑 유사합니다.

 탬플릿 영상을 입력 영상의 좌측 상단에서 시작해서 전체 영역을 스캔합니다.

 템플릿 영상과 입력 영산간 유사도와 비유사도를 실수 형태의 행렬로 반환합니다. (거리의 개념으로 반환)

 유사도와 비유사도를 조사하는지 선택에 따라 최댓값, 최솟값을 중 어떤 값을 봐야하는지 결정됩니다.

 

 필터링이 동작할 때는 영상의 가장자리에 가상의 픽셀이 있다고 가정하고 필터링을 하게 때문에 입력 영상과 동일한 피터 크기의 출력 영상을 만들 수 있지만, 탬플릿 매칭은 가장의 픽셀을 가정하지 않습니다.

 따라서 반환값 행렬은 입력 영상보다 한픽셀 작은 형태로 유사도맵 또는 비유사도맵을 행렬의 형태로 출력합니다.

 그리고 최댓값, 최솟값 위치를 마킹합니다.

 

2. 템플릿 매칭 함수 - cv2.matchTemplate

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

• image: 입력 영상. 8비트 또는 32비트.

• templ: 템플릿 영상. image보다 같거나 작은 크기, 같은 타입.

• method: 비교 방법. cv2.TM_으로 시작하는 플래그 지정. 6가지

• result: 비교 결과 행렬. numpy.ndarray. dtype=numpy.float32. image의 크기가 W X H 이고, templ의 크기가 w X h 이면 result 크기는 (W - w + 1) X (H - h +1).  (가상의 픽셀이 가정되지 않기 때문)

 입력 영상과 템플릿 영상의 크기를 동일하면 1X1 행렬이 나옵니다.

 이 행렬이 유사도 또는 비유사도를 판단하는 행렬이 됩니다.

 

 입력 영상에비해 유사도맵, 비유사도맵은 크기가 작습니다.

 

 반환값 result에 유사도맵 또는 비유사도맵이 저장됩니다.

 

 mask는 입력 영상 전체에서 탬플릿 매칭을 할지, 일부분에서만 탬플릿 매칭을 할지 결정하는 인자입니다.

 

3. 템플릿 매칭 방법 - method 인자

 method 인자는 유사도를 계산할건지 비유사도를 계산할 건지를 플래그로 지정할 수 있습니다.

 6개의 플래그가 지원됩니다.

 

(1) cv2.TM_SQDIFF

 유사하면 0(검은색), 비유사하면 255를 반환합니다.

 

 

 템플릿 영상에서 입력 영상의 부분 영상(같은 위치에 있는)의 픽셀를 뺀 것을 제곱하여 다 더하겠다는 의미입니다.

 템플릿 영상과 구분 영상이 완전히 동일하다고 하면 R의 결과가 0에 가까운 값. 완전히 같으면 0 다르면 값이 커집니다.

 

 

 

 

(2) cv2.TM_SQDIFF_NORMED

 cv2.TM_SQDIFF를 [0, 1]로 정규화한 것입니다.

 

 

 분모에 정규화하는 수식이 추가되었습니다.

 

 

(3) cv2.TM_CCORR

 유사하면 255, 비유사하면 0을 반환합니다.

 

 

 템플릿 영상의 픽셀값과 부분 영상의 픽셀 값을 같은 위치의 픽셀값을 곱하고 다 더하는 방법입니다.

 

 

 원본 영상에서의 흰색 부분은 결과값이 크게 나오는 경향이 있어 메시의 얼굴을 못찾았습니다.

 해결방법은 밝기를 보정하던가 정규화하는 것입니다.

 

(4) cv2.TM_CCORR_NORMED

 cv2.TM_CCORR를 정규화한 것입니다.

 

 

 

(5) cv2.TM_CCOEFF

 밝기를 보정하고 cv2.TM_CCORR방법을 이용합니다.

 유사하면 255, 비유사하면 0을 반환합니다.

 

 

 T' 는 T(템플릿 영상)의 평균 값으로 뺀 값입니다.

 I'는 I(부분 영상)의 평균값으로 뺀 값입니다.

 이 의미는 영상기준으로 평균 크기만큼 빼서 보상을 하여 보정을 하겠다는 방법입니다.

 밝기 보정이 들어가서 결과가 좀 더 좋습니다.

 

 

(6) cv2.TM_CCOEFF_NORMED

 가장 성능이 뛰어나지만 수식이 복잡해서 연산량이 많습니다.

 완전히 일치하면 1, 역일치하면 -1, 상호 연관성이 없으면 0을 반환합니다.

 

 

 

4. 탬플릿 매칭 예제

예제 코드 출처 :  황선규 박사님 github홈페이지

 

『OpenCV 4로 배우는 컴퓨터 비전과 머신 러닝』

예제 소스 코드는 아래 링크를 참고하세요

sunkyoo.github.io

 

 노이즈를 추가하였습니다.

# 입력 영상 & 템플릿 영상 불러오기
src = cv2.imread('circuit.bmp', cv2.IMREAD_GRAYSCALE)
templ = cv2.imread('crystal.bmp', cv2.IMREAD_GRAYSCALE)

if src is None or templ is None:
    print('Image load failed!')
    sys.exit()
    
# 입력 영상 밝기 50증가, 가우시안 잡음(sigma=10) 추가하여 약간의 변형을 줌
noise = np.zeros(src.shape, np.int32)

# cv2.randn은 가우시안 형태의 랜덤 넘버를 지정, 노이즈 영상에 평균이 50 시그마 10인 노이즈 추가
cv2.randn(noise,50,10)

# 노이즈를 입력 영상에 더함, 원래 영상보다 50정도 밝아지고 시그마 10정도 변형
src = cv2.add(src, noise, dtype=cv2.CV_8UC3)

# 탬플릿 매칭 & 결과 분석
res = cv2.matchTemplate(src, templ, cv2.TM_CCOEFF_NORMED) # 여기서 최댓값 찾기

# 최솟값 0, 최댓값 255 지정하여 결과값을 그레이스케일 영상으로 만들기
res_norm = cv2.normalize(res, None, 0, 255, cv2.NORM_MINMAX, cv2.CV_8U)

# 최댓값을 찾아야하므로 minmaxloc 사용, min, max, min좌표, max좌표 반환
_, maxv, _, maxloc = cv2.minMaxLoc(res)

# 탬플릿에 해당하는 영상이 입력 영상에 없으면 고만고만한 값에서 가장 큰 값을 도출.
# 그래서 maxv를 임계값 0.7 or 0.6을 설정하여 템플릿 영상이 입력 영상에 존재하는지 파악
print('maxv : ', maxv)
print('maxloc : ', maxloc) 

# 매칭 결과를 빨간색 사각형으로 표시
# maxv가 어느 값 이상이여야지 잘 찾았다고 간주할 수 있다.
th, tw = templ.shape[:2]
dst = cv2.cvtColor(src, cv2.COLOR_GRAY2BGR)
cv2.rectangle(dst, maxloc, (maxloc[0] + tw, maxloc[1] + th), (0, 0, 255), 2)

# 결과 영상 화면 출력
cv2.imshow('res_norm', res_norm)
cv2.imshow('dst', dst)
cv2.waitKey()
cv2.destroyAllWindows()

 

 


OpenCV 튜토리얼과 황선규 박사님의 'OpenCV 4로 배우는 컴퓨터 비전과 머신 러닝' 을 공부하면서 정리해 보았습니다.

OpenCV 튜토리얼 출처 : docs.opencv.org/4.3.0/d4/dc6/tutorial_py_template_matching.html

 

OpenCV: Template Matching

Goals In this chapter, you will learn Theory Template Matching is a method for searching and finding the location of a template image in a larger image. OpenCV comes with a function cv.matchTemplate() for this purpose. It simply slides the template image o

docs.opencv.org

반응형