본문 바로가기
Study/파이썬

Python OpenCV: 모멘트기반 객체검출

by ChatBotBunny 2021. 4. 29.

이 글은 패스트캠퍼스 황선규 박사님의 ''opencv를 활용한 컴퓨터비전과 딥러닝 올인원 패키지"강의 를 리뷰하였습니다. 


1) 모멘트(Moments) 

- 모멘트(Moments)는 영상의 형태를 표현하는 일련의 실수 값

- 모멘트 기반 객체 검출은 두 개의 외곽선, 그레이스케일 영상을 이용하여 모양을 비교하는 방법입니다.

 

- 특정 함수와 입력영상의 correlation을 계산하여 어떤 영상의 모양정보를 얻어낸다. 

- 함수를 정의하기에 따라서 모멘트를 다르게 정의할수 있음 

- 참고논문: www.sci.utah.edu/~gerig/CS7960-S2010/handouts/Hu.pdf

1. geometric moments

geometric moments

2. Central moments: 객체의 위치가 바뀌어도 동일한 객체를 추출 

3. normalized central moment: centeral moment 정규화 

* HU의 7개 불변 모멘트 사용(중심모멘트를 조합해 만든 7개의 모멘트값) => 영상의 크기, 회전, 이동, 대칭에 대해서 모멘트 값이 불변하게 됨.

 

2) OpenCV의 모양비교함수: matchShapes 

cv2.matchShapes(contour1, contour2, method, parameter) -> retval
- 제약사항: 비교하려는 객체가 찌그러지거나 심하게 와핑되있는 경우 결과값이 좋지않을수 있음. 
• contour1: 첫 번째 외곽선 자체 또는 그레이스케일 영상, 외곽선 정보는 findcontour로 검출한 외곽선 정보를 입력해도 됨. 
• contour2: 두 번째 외곽선 또는 그레이스케일 영상 - findcontour로 검출한 외곽선 정보를 입력해도 됩니다.
• method: 비교 방법 지정. contours_match_l3이 추천됨.  


• parameter: 사용되지 않음. 0 지정.
• retval: 두 외곽선 또는 그레이스케일 영상 사이의 거리(distance)->차이가 크면 큰값 리턴, 작으면 작은값 리턴 

 

example1) 

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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
import sys
import numpy as np
import cv2
 
# goal: 여러개의 객체가 담겨있는 이미지에서 타겟 객체를 분리해내기 
 
#%% 영상 불러오기
obj = cv2.imread('spades.png', cv2.IMREAD_GRAYSCALE) # 타겟 
src = cv2.imread('symbols.png', cv2.IMREAD_GRAYSCALE) # 이미지 
 
if src is None or obj is None:
    print('Image load failed!')
    sys.exit()
 
# 객체 영상 외곽선 검출
_, obj_bin = cv2.threshold(obj, 128255, cv2.THRESH_BINARY_INV)
# obj_bin: obj영상의 객체가 검정색이기때문에 반전하여 obj_bin에 저장 
obj_contours, _ = cv2.findContours(obj_bin, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
obj_pts = obj_contours[0]
 
# 입력 영상 분석
_, src_bin = cv2.threshold(src, 128255, cv2.THRESH_BINARY_INV)
contours, _ = cv2.findContours(src_bin, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
 
# 결과 영상
dst = cv2.cvtColor(src, cv2.COLOR_GRAY2BGR)
 
# 입력 영상의 모든 객체 영역에 대해서
for pts in contours: # pts: 객체 한개의 외곽선 정보 
    if cv2.contourArea(pts) < 1000# contourAreas: 객체의 area 계산. 
        continue                    # area가 너무 작으면 노이즈 라고 판단. 
 
    rc = cv2.boundingRect(pts)
    cv2.rectangle(dst, rc, (25500), 1)
 
    # 모양 비교
    dist = cv2.matchShapes(obj_pts, pts, cv2.CONTOURS_MATCH_I3, 0# distance
 
    # distance값 화면에 출력 
    cv2.putText(dst, str(round(dist, 4)), (rc[0], rc[1- 3),
                cv2.FONT_HERSHEY_SIMPLEX, 0.6, (25500), 1, cv2.LINE_AA)
 
    if dist < 0.1# distance가 0.1보다 작으면 bounding box를 빨강색으로 그려라 
        cv2.rectangle(dst, rc, (00255), 2)
 
cv2.imshow('obj', obj)
cv2.imshow('dst', dst)
cv2.waitKey(0)
cs

Result