Python과 OpenCV – 18 : 이미지의 등치선(Contours) – 4/5

이 글의 원문은 https://opencv-python-tutroals.readthedocs.io/en/latest/py_tutorials/py_imgproc/py_contours/py_contours_more_functions/py_contours_more_functions.html#contours-more-functions 입니다.

등치선에 대한 볼록껍질(Convex Hull) 연산에서 오목한 부분(즉, 블럭한 부분에 대한 결합)을 발견하는 함수와 등치선으로 만들어지는 도형(또는 객체)와 임이의 포인트에서의 거리를 구하는 함수, 마지막으로 객체간의 유사성 정도를 하나의 값으로 특정하는 함수에 대해 정리합니다.

먼저 볼록 껍질 연산에서 오목한 부분을 식별하는 예제는 아래와 같습니다.

import numpy as np
import cv2
 
img = cv2.imread('./data/thunder.png')
imgray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
ret,thresh = cv2.threshold(imgray,127,255,0)
image, contours, hierarchy = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
 
cnt = contours[0]
hull = cv2.convexHull(cnt,returnPoints = False)
defects = cv2.convexityDefects(cnt,hull)

print(defects)

for i in range(defects.shape[0]):
    s,e,f,d = defects[i,0]
    start = tuple(cnt[s][0])
    end = tuple(cnt[e][0])
    far = tuple(cnt[f][0])
    cv2.line(img,start,end,[0,255,0],2)
    cv2.circle(img,far,5,[0,0,255],-1)

cv2.imshow('img', img)
cv2.waitKey()
cv2.destroyAllWindows()

결과는 아래와 같은데요..

작은 빨간 원으로 표시되는 부분이 볼록껍질 연산에 있어서 오목한 부분으로 식별된 지점입니다. 그리고 초록색선은 오목한 지점에 대해 볼록하게 처리된 선분입니다.

등치선으로 구성된 객체에 대해 어떤 좌표에서의 거리를 얻는 예제는 다음과 같습니다.

dist = cv2.pointPolygonTest(cnt,(50,50),True)

위의 예제는 (50,50) 좌표에서 등치선까지의 거리를 얻습니다. 등치선으로 구성된 도형의 내부에 포인트 좌표(여기서는 50,50)이 존재하면 양수가, 밖에 존재하면 음수가, 등치선 상에 정확이 위치하면 0인 거리가 반환됩니다. pointPolygonTest 함수의 세번째 인자는 True인데, 이를 False로 지정하면 거리값이 아닌 -1, 0, 1 중 하나의 값이 반환됩니다. 이값들은 각각 도형의 외부, 경계, 내부인지의 여부를 나타내는 부호값입니다.

마지막으로 도형에 대해 유사성을 하나의 수치값으로 특정할 수가 있는데, 예제를 살펴보면..

import numpy as np
import cv2

img1 = cv2.imread('./data/shapes/1.png')
img1 = cv2.cvtColor(img1,cv2.COLOR_BGR2GRAY)

img2 = cv2.imread('./data/shapes/2.png')
img2 = cv2.cvtColor(img2,cv2.COLOR_BGR2GRAY)

ret, thresh1 = cv2.threshold(img1, 127, 255,0)
ret, thresh2 = cv2.threshold(img2, 127, 255,0)

_, contours,hierarchy = cv2.findContours(thresh1,2,1)
cnt1 = contours[0]

_, contours,hierarchy = cv2.findContours(thresh2,2,1)
cnt2 = contours[0]

ret = cv2.matchShapes(cnt1,cnt2,1,0.0)
print(ret)

위의 예제는 1.png 파일과 2.png 파일에 대한 등치선을 추출하고 이 등치선으로 구성된 도형에 대한 유사성을 하나의 값으로 특정하는 예제입니다. 입력 이미지 파일이 아래와 같은데요. 파일명만 표시하고 확장자인 png는 생략되었습니다.

1.png 파일에 대해 나머지 파일들에 대한 유사성 값을 위의 코드를 통해 출력해보면 각각 아래와 같습니다.

1.png와 2.png 간의 cv2.matchShapes 반환값 = 0.16
1.png와 3.png 간의 cv2.matchShapes 반환값 = 14.1
1.png와 4.png 간의 cv2.matchShapes 반환값 = 0.11
1.png와 5.png 간의 cv2.matchShapes 반환값 = 0.26
1.png와 6.png 간의 cv2.matchShapes 반환값 = 0.26
1.png와 7.png 간의 cv2.matchShapes 반환값 = 0.32
1.png와 8.png 간의 cv2.matchShapes 반환값 = 0.32
1.png와 9.png 간의 cv2.matchShapes 반환값 = 0.17
1.png와 10.png 간의 cv2.matchShapes 반환값 = 0.005
1.png와 11.png 간의 cv2.matchShapes 반환값 = 1.03

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다