728x90
예제
전체 예제 코드입니다.
import os
import math
import cv2
def setLabel(img, pts, label):
(x, y, w, h) = cv2.boundingRect(pts)
pt1 = (x, y)
pt2 = (x + w, y + h)
cv2.rectangle(img, pt1, pt2, (0, 255, 0), 2)
cv2.putText(img, label, (pt1[0], pt1[1]-3), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 255))
path = os.path.join('img', 'shape.png')
img = cv2.imread(path)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
ret, thr = cv2.threshold(gray, 0, 255, cv2.THRESH_OTSU)
contours, _ = cv2.findContours(thr, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
for cont in contours:
approx = cv2.approxPolyDP(cont, cv2.arcLength(cont, True) * 0.02, True)
vtc = len(approx)
if vtc == 3:
setLabel(img, cont, 'Tri')
elif vtc == 4:
setLabel(img, cont, 'Rec')
elif vtc == 5:
setLabel(img, cont, 'Pen')
else:
area = cv2.contourArea(cont)
_, radius = cv2.minEnclosingCircle(cont)
ratio = radius * radius * math.pi / area
if int(ratio) == 1:
setLabel(img, cont, 'Cir')
cv2.imshow('img', img)
cv2.imshow('binary', thr)
cv2.waitKey()
cv2.destroyAllWindows()
사용한 이미지입니다.
이미지를 불러오고 그레스케일로 변환한 후에 이진화를 합니다.
img = cv2.imread(path)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
ret, thr = cv2.threshold(gray, 0, 255, cv2.THRESH_OTSU)
외곽선을 검출합니다.
계층정보는 필요없어서 생략했구요.
contours, _ = cv2.findContours(thr, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
검출된 외곽선들을 반복하면서 꼭지점을 구합니다.
for cont in contours:
approx = cv2.approxPolyDP(cont, cv2.arcLength(cont, True) * 0.02, True)
vtc = len(approx)
cv2.approxPolyDP(curve, epsilon, closed, approxCurve=None) -> approxCurve
-
curve: 외곽선 좌표 (contour)
-
epsilon: 극사화 정밀도 (cv2.arcLength(pts, True) * 0.01 ~ 0.05 로 많이 사용)
-
closed: True (폐곡선)
-
approxCurve: 극사화된 곡선의 좌표
cv2.arcLength(curve, closed) -> retval
-
curve: 외곽선 좌표 (contour)
-
closed: True (폐곡선)
-
retval: 외곽선 길이 (폐곡선이라면 둘레)
꼭지점 개수가 3이면 삼각형, 4이면 사각형, 5이면 오각형으로 식별했습니다.
if vtc == 3:
setLabel(img, cont, 'Tri')
elif vtc == 4:
setLabel(img, cont, 'Rec')
elif vtc == 5:
setLabel(img, cont, 'Pen')
다음은 원인데요.
다음과 같이 두 식의 결과를 비교해서 원이라고 식별했습니다.
area = cv2.contourArea(cont)
_, radius = cv2.minEnclosingCircle(cont)
ratio = radius * radius * math.pi / area
if int(ratio) == 1:
setLabel(img, cont, 'Cir')
cv2.contourArea(curve, oriented=None) -> retval
-
curve: 외곽선 좌표 (contour)
-
oriented(default=False)
-
True: 외곽선 진행 방향이 시계/반시계 방향에 따라 +/-
-
False: 항상 +
-
retval: 외곽선으로 둘러 쌓인 영역의 면적
cv2.minEnclosingCircle(curve) -> center, radius
-
curve: 외곽선 좌표 (contour)
-
center: bounding circle 의 중심 좌표 (x, y)
-
radius: bounding circle 의 반지름(실수)
'OpenCV' 카테고리의 다른 글
파이썬 OpenCV 템플릿 매칭 -2 : 크롬 공룡게임 실시간 매칭하기 (2) | 2020.08.06 |
---|---|
파이썬 OpenCV 템플릿 매칭 -1 : 크롬 공룡게임 (0) | 2020.08.06 |
파이썬 OpenCV 라벨링(Labeling) (0) | 2020.07.26 |
파이썬 OpenCV 외곽선 검출(Contours) (0) | 2020.07.26 |
파이썬 OpenCV 이미지 이진화(Binarization) : threshold otsu adaptiveThreshold (0) | 2020.07.26 |