황선규 박사님의 'OpenCV 4로 배우는 컴퓨터 비전과 머신 러닝' 을 공부하면서 정리해 보았습니다.
OpenCV 명령어 출처 : docs.opencv.org/4.3.0/dd/d49/tutorial_py_contour_features.html
예제 코드 출처 : 황선규 박사님 github홈페이지
다양한 외곽선 함수
외곽선 함수에 대한 자세한 정보는 docs.opencv.org/4.3.0/dd/d49/tutorial_py_contour_features.html 에서 확인하실 수 있습니다.
(1) cv.arcLength()
외곽선 길이를 반환합니다.
(2) cv2.contourArea()
외곽선이 감싸는 영역의 면적을 반환합니다.
(3) cv2.boundingRect()
주어진 점을 감싸는 최소 크기 사각형(바운딩 박스)를 반환합니다.
(4) cv2.minEnclosingCircle()
주어진 점을 감싸는 최소 크기 원을 반환합니다.
(5) cv2.minAreaRect()
주어진 점을 감싸는 최소 크기 회전된 사각형을 반환합니다.
(6) cv2.minEnclosingTriangle()
주어진 점을 감싸는 최소 크기 삼각형을 반환합니다.
(7) cv2.approxPolyDP()
외곽선을 근사화(단순화) 합니다.
(8) cv2.fitEllipse()
주어진 점에 적합한 타원을 반환합니다.
(9) cv2.fitLine()
주어진 점에 적합한 직선을 반환합니다.
(10) cv2.isContourConvex()
컨벡스 인지를 검사합니다.
(11) cv2.convexHull()
주어진 점으로부터 컨벡스 헐을 반환합니다.
(12) cv2.convexityDefects()
주어진 점과 컨벡스 헐로부터 컨벡스 디펙트를 반환합니다.
자주 쓰이는 외곽선 함수 설명
1. 외곽선 길이 구하기 - cv2.arcLength()
cv2.arcLength(curve, closed) -> retval
• curve: 외곽선 좌표. numpy.ndarray. shape=(K, 1, 2)
• closed: True이면 폐곡선으로 간주
• retval: 외곽선 길이
2. 면적 구하기 - cv2.contourArea()
cv2.contourArea(contour, oriented=None) -> retval
• contour: 외곽선 좌표. numpy.ndarray. shape=(K, 1, 2)
• oriented: True이면 외곽선 진행 방향에 따라 부호 있는 면적을 반환. 기본값은 False.
• retval: 외곽선으로 구성된 영역의 면적
3. 바운딩 박스(외곽선을 외접하여 둘러싸는 가장 작은 사각형) 구하기 - cv2.boundingRect()
cv2.boundingRect(array) -> retval
• array: 외곽선 좌표. numpy.ndarray. shape=(K, 1, 2)
• retval: 사각형 정보. (x, y, w, h) 튜플.
4. 바운딩 서클(외곽선을 외접하여 둘러싸는 가장 작은 원) 구하기
cv2.minEnclosingCircle(points) -> center, radius
• points: 외곽선 좌표. numpy.ndarray. shape=(K, 1, 2)
• center: 바운딩 서클 중심 좌표. (x, y) 튜플.
• radius: 바운딩 서클 반지름. 실수
5. 외곽선 근사화 - cv2.approxPolyDP
cv2.approxPolyDP(curve, epsilon, closed, approxCurve=None) -> approxCurve
• curve: 입력 곡선 좌표. numpy.ndarray. shape=(K, 1, 2)
• epsilon: 근사화 정밀도 조절. 입력 곡선과 근사화 곡선 간의 최대 거리. e.g) cv2.arcLength(curve) * 0.02
• closed: True를 전달하면 폐곡선으로 인식
• approxCurve: 근사화된 곡선 좌표. numpy.ndarray. shape=(K', 1, 2)
더글라스-포이커 알고리즘6. Convex 검사 - cv2.isContourConvex
cv2.isContourConvex(contour) -> retval
• contour: 입력 곡선 좌표. numpy.ndarray. shape=(K, 1, 2)
• retval: 컨벡스이면 True, 아니면 False
다각형 판별 프로그램 예제
황선규 박사님의 깃허브에 있는 다각형 판별 프로그램 입니다.
원을 판별하는 방법은 도형의 넓이와 도형을 감싸고 있는 외곽선 길이의 비율을 검사합니다.
하나의 끈으로 만든 가장 면적이 큰 도형은 원입니다.
분모는 외곽선 길이, 분자는 도형의 넓이를 이용합니다.
A/P를 구하면 미지수 r이 남게 되므로 P를 제곱하여 구합니다.
값이 1에 가까울수록 원으로 판단합니다.
# 사각형을 그리는 함수
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, 0, 255), 1)
cv2.putText(img, label, pt1, cv2.FONT_HERSHEY_PLAIN, 1, (0, 0, 255))
def main():
img = cv2.imread('polygon.bmp', cv2.IMREAD_COLOR)
if img is None:
print('Image load failed!')
return
# 그레이스케일 영상으로 변환
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 이진화, INV 이유는 배경이 흰색, 객체가 어두운 영상이므로
_, img_bin = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV | cv2.THRESH_OTSU)
# 외곽선 검출, EXTERNAL로 바깥 외곽선만 도출
contours, _ = cv2.findContours(img_bin, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
# 외곽선 좌표 받아오기
for pts in contours:
if cv2.contourArea(pts) < 400: # 노이즈 제거, 너무 작으면 무시
continue
# 근사화
approx = cv2.approxPolyDP(pts, cv2.arcLength(pts, True)*0.02, True)
# 근사화 결과 점 갯수
vtc = len(approx)
# 3이면 삼각형
if vtc == 3:
setLabel(img, pts, 'TRI')
# 4면 사각형
elif vtc == 4:
setLabel(img, pts, 'RECT')
else:
length = cv2.arcLength(pts, True)
area = cv2.contourArea(pts)
ratio = 4. * math.pi * area / (length * length)
if ratio > 0.85:
setLabel(img, pts, 'CIR')
cv2.imshow('img', img)
cv2.waitKey()
cv2.destroyAllWindows()
if __name__ == '__main__':
main()
'etc > FastCampus 챌린지' 카테고리의 다른 글
패스트캠퍼스 OpenCV를 활용한 컴퓨터비전과 딥러닝 올인원 패키지 Online 챌린지 참여 후기!!!!!!!!!!!!!! (0) | 2020.12.24 |
---|---|
[패스트캠퍼스 수강 후기] 컴퓨터비전인강 100% 환급 챌린지 49 회차 (0) | 2020.12.06 |
[패스트캠퍼스 수강 후기] 컴퓨터비전인강 100% 환급 챌린지 47 회차 (0) | 2020.12.04 |
[패스트캠퍼스 수강 후기] 컴퓨터비전인강 100% 환급 챌린지 46 회차 (0) | 2020.12.03 |
[패스트캠퍼스 수강 후기] 컴퓨터비전인강 100% 환급 챌린지 45 회차 (0) | 2020.12.02 |