Computer Vision/opencv(python)

[46] 8) 다양한 외곽선 함수

jwjwvison 2021. 3. 24. 01:01
  • 외곽선 관련 함수

 

  • 외곽선 길이 구하기
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) -> 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)

  • Convex 검사
cv2.isContourConvex(contour) -> retval

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

 

  • 다각형 검출 프로그램
    • 다양한 다각형 객체 영상에서 삼각형, 사각형, 원 찾기
  • 구현 순서

 

 

  • 다각형 판별 프로그램 예제
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,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)
    _,img_bin=cv2.threshold(gray,0,255,cv2.THRESH_BINARY_INV | cv2.THRESH_OTSU)
    #도형들이 배경보다 밝은 사진이기 때문에 INV를 해주어야 한다
    contours,_=cv2.findContours(img_bin,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_NONE)
    # EXTERNAL을 통해 바깥쪽에 있는 것만 검출
    
    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')
        elif vtc==10:
            setLabel(img,pts,'STAR')
        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')
            elif 0.70<ratio<0.85:
                setLabel(img,pts,'ELLIPSE')
            else:
                setLabel(img,pts,'POLY')

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

if __name__ == '__main__':
    main()