[ch07] 이진 영상 처리 - 다양한 외곽선 함수

빨주노·2021년 8월 27일
0

외곽선 관련 함수

외곽선 길이 구하기

cv2.arcLength(curve, closed) -> retval
  • curve : 외곽선 좌표. numpy.ndarray.shape=(K, 1, 2)
  • closed : True이면 폐곡선으로 간주
  • retval : 외곽선 길이

면적 구하기

cv2.contourArea(contour, oriented=None) -> retval
  • contour : 외곽선 좌표. numpy.ndarray.shape=(K, 1, 2)
  • oriented : True이면 외곽선 진행 방향에 따라 부호 있는 면적을 반환. 기본값은 False
  • retval : 외곽선으로 구성된 영역의 면적

바운딩 박스(외곽선을 외접하여 둘러싸는 가장 작은 사각형) 구하기

cv2.boundingRect(array) -> retval
  • array : 외곽선 좌표. numpy.ndarray.shape=(K, 1, 2)
  • retval : 사각형 정보. (x, y, w, h) 튜플

바운딩 서클(외곽선을 외접하여 둘러싸는 가장 작은 원) 구하기

cv2.minEnclosingCircle(points) -> center, radius
  • points : 외곽선 좌표. numpy.ndarray.shape=(K, 1, 2)
  • center : 바운딩 서클 중심 좌표. (x, y) 튜플
  • radius : 바운딩 서클 반지름. 실수.

외곽선 근사화

cv2.approxPolyDP(curve, epsilon, closed, approxCurve=None) -> retval
  • curve : 입력 곡선 좌표. numpy.ndarray.shape=(K, 1, 2)
  • epsilon : 근사화 정밀도 조절. 입력 곡선과 근사화 곡선 간의 최대 거리.
    • ex) cv2.arcLength(curve) * 0.02
  • closed : True를 전달하면 폐곡선으로 인식
  • approxCurve : 근사화된 곡선 좌표. numpy.ndarray.shape=(K', 1, 2)
  • 참고사항
    • 더글라스-포이커 알고리즘 (Douglas-peucker algorithm)

Convex 검사

cv2.isContourConvex(contour) -> retval
  • contour : 입력 곡선 좌표. numpy.ndarray.shape=(K, 1, 2)
  • retval : 컨벡스이면 True, 아니면 False.

다각형 검출 프로그램

  • 다양한 다각형 객체 영상에서 삼각형, 사각형, 원 찾기
  • 구현 순서
    • 이진화
    • 외곽선 찾기
    • 외곽선 근사화
    • 너무 작은 객체와 컨벡스가 아닌 객체 제외
    • 꼭지점 개수 확인
      - 삼각형, 사각형 검출
      - 원 판별

원 판별하기

  • 정해진 외곽선 길이에 대한 넓이 비율이 가장 큰 형태가 원 → 도형의 넓이(A)와 외곽선 길이(P)의 비율을 검사

    AP\frac{A}{P}의 경우 약분하면 rr이 남게 되어 비율이 상수로 떨어지지 않는다. 따라서 AP²\frac{A}{P²}로 만들어 비율을 계산해준다.

  • 4πAP²4\pi\frac{A}{P²} 값이 1에 가까울수록 원으로 판단
length = cv2.arcLength(pts, True)
area = cv2.contourArea(pts)
ratio = 4. * math.pi * area / (length * lenght)

if ratio > 0.05:
    setLabel(img, pts, 'CIR') # 원

다각형 판별 프로그램 예제

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))

img = cv2.imread('polygon.bmp', cv2.IMREAD_COLOR)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
_, img_bin = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV | cv2.THRESH_OTSU)
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)
    
    if vtc == 3:
        setLabel(img, pts, 'TRI')
    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')

profile
딥 하게 딥러닝 하는중

0개의 댓글