[OpenCV-python] Contour 응용하기 2

2018. 6. 8. 20:03Python-이론/python-opencv

contour 응용하기 2



Convex Hull


Convex Hull(볼록체) 사용하여 오목한 부분이 있는지 체크하고 있다면 없애버리는 것을 말합니다. 


제가 손으로 그린 모자입니다. 

이 그림에는 오목한 부분이 있는지 두군대가 있는데요 contour을 오목한 부분에 안가고 볼록한 부분으로만 가게 만들어 보겠습니다.



예제 코드


import cv2

img = cv2.imread('images/hat.png')
img1 = img.copy()
imgray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
ret, thr = cv2.threshold(imgray, 127, 255, cv2.THRESH_BINARY)
_, contour, _ = cv2.findContours(thr, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

cnt = contour[1]
cv2.drawContours(img, [cnt], -1, (255, 0, 0), 2)
check = cv2.isContourConvex(cnt)
cv2.namedWindow('hull', cv2.WINDOW_NORMAL)
cv2.namedWindow('contour', cv2.WINDOW_NORMAL)
if not check:
    hull = cv2.convexHull(cnt)
    cv2.drawContours(img1, [hull], -1, (0, 255, 0), 2)
    cv2.imshow('hull', img1)
cv2.imshow('contour', img)
cv2.waitKey(0)
cv2.destroyAllWindows()

결과




왼쪽의 결과를 보면 두개의 오목한 부분을 피해서 contour이 그려졌다. 


코드 설명


check = cv2.isContourConvex(cnt)

contour에 오목한 부분이 있는지 체크하고 있다면 False 없다면 True를 반환한다. 


 hull = cv2.convexHull(cnt)

contour에 있는 오목한 부분을 제거한다.


다음에 drawContour에 hull을 사용하면 위와 같은 결과가 나온다. 


BoundingRectangle, MinAreaRect


이번에는 controus에 직사각형을 다른 2개의 형태로 나타내 보겠습니다. 


예제 코드



import cv2
import numpy as np
img = cv2.imread('images/purpleStar.png')
imgray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

ret, thr = cv2.threshold(imgray, 127, 255, cv2.THRESH_BINARY)

_, contour, _ = cv2.findContours(thr, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
cnt = contour[1]

x, y, w, h = cv2.boundingRect(cnt)
cv2.rectangle(img, (x, y), (x+w, h+y), (255, 0, 0), 2)

rect = cv2.minAreaRect(cnt)
box = cv2.boxPoints(rect)
box = np.int0(box)
print(box)
cv2.drawContours(img, [box], -1, (0, 0, 255), 2)
cv2.imshow('contour', img)

cv2.waitKey(0)
cv2.destroyAllWindows()


결과 



코드 설명


x, y, w, h = cv2.boundingRect(cnt) cv2.rectangle(img, (x, y), (x+w, h+y), (0, 255, 0), 2)

contour중 하나를 직사각형 형태로 x, y, w, h로 반환한다. contour의 외각으로 직사각형을 그리게 된다. 


rect = cv2.minAreaRect(cnt)
box = cv2.boxPoints(rect)
box = np.int0(box)

첫 함수는 contour에 외접하면서 가장 작은 직사각형을 구하는데 활용된다. 두번째 줄의 코드는 직사각형의 꼭짓점 값을 반환해준다. 

contour을 그리기 위해선 float형이 아니라 int형이여야 되기 때문에 3번째 코드가 필요하다. 


Minimum Enclosing Circle, Fitting Ellipse


이번에는 최소 원 딱 맞는 타원, 선 등을 그려보겠습니다. 


예제코드


import cv2

img = cv2.imread('images/purpleStar.png')
imgray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

ret, thr = cv2.threshold(imgray, 127, 255, cv2.THRESH_BINARY)
_, contour, _ = cv2.findContours(thr, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

con = contour[1]

(x, y), r = cv2.minEnclosingCircle(con)
cv2.circle(img, (int(x), int(y)), int(r), (0, 0, 255), 2)

ellipse = cv2.fitEllipse(con)
cv2.ellipse(img, ellipse, (0, 255, 0), 2)
cv2.imshow('img', img)
cv2.waitKey(0)
cv2.destroyAllWindows()

결과



설명


(x, y), r = cv2.minEnclosingCircle(con)
cv2.circle(img, (int(x), int(y)), int(r), (0, 0, 255), 2)

minEnclosingCircle은 contour에 외접하는 원을 얻기위해 사용한다. 반환값은 (x, y), r로 받아주며 각 값은 float형이기 때문에 int형으로 변환이 필요하다. 


ellipse = cv2.fitEllipse(con)
cv2.ellipse(img, ellipse, (0, 255, 0), 2)

fitEllipse는 contour에서 최적으로 둘러쌓인 타원을 얻을 수 있다. 

'Python-이론 > python-opencv' 카테고리의 다른 글

opencv 설치하기  (0) 2019.06.29
[OpenCV-python] resize, rotation, move, perspective  (0) 2018.06.13
[OpenCV-python] Contour 응용하기 1  (1) 2018.06.07
[OpenCV-python] Contour  (0) 2018.06.07
[OpenCV-python] adaptive Threshold  (0) 2018.06.06