728x90
728x90
템플릿 매칭(Template matching)이란?
- Classification
• 입력 영상에서 (작은 크기의) 템플릿 영상과 일치하는 부분을 찾는 기법
• 템플릿: 찾을 대상이 되는 작은 영상. 패치(patch)
기본적으로 같은 위치의 픽셀끼리 곱하고 다 더해서 유사도를 판단
==> 회전, 크기변환이 클 때는 찾기 어려움
==> Key point활용(= Local feature matching)
유사도 => 최댓값(비슷한 부분이 밝게)
비유사도 => 최솟값(비슷한 부분이 어둡게)
==> 거리를 나타낸다
OpenCV filter VS Template filter
OpenCV filtering은 영상 이미지의 가상의 픽셀(padding)이 있다는 가정하에 filter를 돌린다
== 동일한 크기를 얻을 수 있다.
But
Template은 가상의 필터가 없음(= 영상안에서만 scanning)
== 주변 테두리가 검은색으로 나온다
# templ 위치 찾기
src = cv2.imread('ch08\\images\\circuit.bmp', cv2.IMREAD_GRAYSCALE)
templ = cv2.imread('ch08\\images\\crystal.bmp', cv2.IMREAD_GRAYSCALE)
if src is None or templ is None:
print('Image load failed!')
sys.exit()
# noise 추가
# 입력 영상 밝기 50증가, 가우시안 잡음(sigma=10) 추가
# np.random.normal(loc=0.0, scale=1.0, size=None)
# 평균, 표준편차
noise = np.zeros(src.shape, np.int32)
cv2.randn(noise, 50, 10)
src_noise = cv2.add(src, noise, dtype=cv2.CV_8UC3)
# 템플릿 매칭 & 결과 분석
res = cv2.matchTemplate(src_noise, templ, cv2.TM_CCOEFF_NORMED)
# 영상을 보기 위함(normalize) = 유난히 밝은 흰색 부분을 찾을 수 있음
res_norm = cv2.normalize(res, None, 0,255, cv2.NORM_MINMAX, cv2.CV_8U)
'''
cv2.matchTemplate(image, templ, method, result=None, mask=None) -> result
image와 templ는 8비트 or 32비트
result= (W - w + 1) * (H - h +1) = 32비트의 단일 채널 이미지로 반환
W, H = 입력 영상의 이미지
w, h = template 이미지
method = SQDIFF(완전히 같으면 0, 다르면 값이 커짐)
CCORR(같으면 큰값, 다르면 작은 값)
CCOEFF_NORMED(완전히 일치하면 1, 역일치 -1, 연관성 없으면 0)
'''
# minv, maxv, minloc, maxloc(위치)
_, maxv, _, maxloc = cv2.minMaxLoc(res)
'''
Tip : cv2.TM_SQDIFF, cv2.TM_SQDIFF_NORMED는 최소 지점(minLoc)이 검출된 위치
Tip : cv2.TM_CCORR, cv2.TM_CCORR_NORMED, cv2.TM_CCOEFF, cv2.TM_CCOEFF_NORMED는
최대 지점(maxLoc)이 검출된 위치
'''
print('maxv:', maxv)
print('maxloc:', maxloc) # x, y
'''
maxv: 0.9796600341796875
maxloc: (568, 320)
'''
# 매칭 결과를 빨간색 사각형으로 표시
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('src', src)
cv2.imshow('templ', templ)
cv2.imshow('src_noise', src_noise)
cv2.imshow('src', src)
cv2.imshow('dst', dst)
cv2.waitKey()
method
SQDIFF - Distance를 반환
* 상관계수 = [-1, 0 ,1] 사이 값을 가짐
CCOEFF - 밝기에 대한 보정을 한 후에 Correlation= 결과가 좋음
CCOEFF_NORMED - 연산량이 많다는 단점 but 성능이 제일 좋음
* Tip
만약 내가 찾고자하는 이미지가 없는 이미지에서 실행을 한다?
어느 위치든 박스를 그려 찾아낼 것이다
즉, 찾고자하는 객체가 있으면 maxv가 큰 값을 가질테고
없다면 고만고만한것으로 return 하게 될것인데
이는 Threshold(임계값)을 부여해서 임계값보다 클 경우에만 있다고 판단하게 할 수 있다.
인식(Recognition)이란?
- 인식이라는 단어는 너무 거창함
- Classification
- 고양이를 보고 단순히 고양이라고 판단하는 것이 아니라 해당 고양이 사진과
내가 가지고 있는 고양이 정보와 비교하여 비슷한지를 판단
• Classifying a detected object into different categories.
• 여러 개의 클래스 중에서 가장 유사한 클래스를 선택
숫자인식
src = cv2.imread('ch08\\images\\digits_print.bmp')
if src is None:
print('Image load failed!')
sys.exit()
# load_images 폴더 이미지 불러오기
def load_digits():
img_digits = []
for i in range(10):
filename = f'ch08\\digits\\digit{i}.bmp'
img_digits.append(cv2.imread(filename, cv2.IMREAD_GRAYSCALE))
if img_digits[i] is None:
print(('Image load failed'))
return None
return img_digits
# 숫자(index)를 반환
def find_digit(img, img_digits):
max_idx = -1
max_ccoeff = -1
for i in range(10):
# img_digits.shape (150, 100)
img = cv2.resize(img, (100, 150))
res = cv2.matchTemplate(img, img_digits[i], cv2.TM_CCOEFF_NORMED)
# res = img 영상과, img_digits 영상의 크기가 같으면 (1*1)행렬로 나옴
# -1 ~ 1 의 값이 나옴
# == 즉, 최대값을 찾겠다는 code
if res[0,0] > max_ccoeff:
max_idx = i
max_ccoeff = res[0,0]
return max_idx
# load_digits 함수, 폴더에 있는 이미지 다 불러오기
img_digits = load_digits() # list
print(img_digits[0].shape)
# 입력 영상 이진화 & 레이블링
src_gray = cv2.cvtColor(src, cv2.COLOR_BGR2GRAY)
_, src_bin = cv2.threshold(src_gray, 0, 255, cv2.THRESH_BINARY_INV | cv2.THRESH_OTSU)
cnt, _, stats, _ = cv2.connectedComponentsWithStats(src_bin)
# 숫자 인식 결과 영상 생성
dst = src.copy()
for i in range(1, cnt):
(x, y, w, h, area) = stats[i]
if area < 1000:
continue
# 가장 유사한 숫자 이미지를 선택
# find_digit
digit = find_digit(src_gray[y:y+h, x:x+w], img_digits)
cv2.rectangle(dst, (x,y,w,h), (0,255,255))
cv2.putText(dst, str(digit), (x, y - 4), cv2.FONT_HERSHEY_SIMPLEX,\
0.7, (0,0,255), 1, cv2.LINE_AA)
cv2.imshow('src', src)
cv2.imshow('dst', dst)
cv2.waitKey()
728x90
'OpenCV > OpenCV-Chapter' 카테고리의 다른 글
CH08 OpenCV-Python HOG 보행자 검출 (0) | 2021.12.24 |
---|---|
CH08 OpenCV-Python 캐스케이드(Cascade) (0) | 2021.12.24 |
CH08 OpenCV-Python Moment 기반 객체 검출 (0) | 2021.12.24 |
CH08 OpenCV-Python 영상 분할 그랩컷(GrabCut) (0) | 2021.12.24 |
CH07 OpenCV-Python 객체 단위 분석(Labeling) (0) | 2021.12.24 |
댓글