Prerequisite : 윤곽선 길이 구하기, Convex hull

볼록 결함 찾기

지난 시간에 Convex hull에 대해서 알아보았다. 이 포스팅에서는 볼록 결함(convexity defect)를 찾는 방법에 대해서 알아본다.

볼록 결함이란 convex hull로 부터 오목하게 들어간 윤곽선 중 가장 멀리 떨어진 부분을 찾는 방법이라고 할 수 있다.

자세한 내용은 stackoverflow의 한 답변으로 대체한다.

OpenCV에서는 이 볼록 결함을 찾기위해 convexityDefects라는 함수를 제공한다.

Imgproc.convexityDefects(contour, convexHull, convexityDefects)

contour: 윤곽선 좌표 정보
convexHull: convex hull 정보
convexityDefects: 함수 호출 후 참조 할 볼록 결함 정보

Convex hull 포스팅에서 다뤘던 손 모양 예제를 수정하여 넣어볼록 결함을 찾아보자.

볼록결함을 파란색원으로 나타내고 있다.

예제코드:

val contours = ArrayList<MatOfPoint>()
val hierarchy = Mat()

//윤곽선 검출
Imgproc.findContours(
    binary,
    contours,
    hierarchy,
    Imgproc.RETR_TREE,
    Imgproc.CHAIN_APPROX_SIMPLE
)
for (i in 0 until contours.size) {
    // 윤곽선 근사화, (근사화 하지 않으면 의도했던 결과보다 많은 볼록결함이 발견된다)
    val contour2f = MatOfPoint2f(*contours[i].toArray())
    val approxContour = MatOfPoint2f()
    Imgproc.approxPolyDP(
        contour2f,
        approxContour,
        Imgproc.arcLength(contour2f, true)*(0.005),
        true
    )
    val convexHull = MatOfInt()
    
    // 컨벡스 헐 찾기
    val contour = MatOfPoint(*approxContour.toArray())
    Imgproc.convexHull(contour, convexHull)
    
    // 컨벡스 헐 정점만 추려내기
    val contourArray: Array<Point> = contour.toArray()
    val hullPoints: Array<Point?> = arrayOfNulls<Point>(convexHull.rows()
    val hullContourIdxList = convexHull.toList()
    for (j in hullContourIdxList.indices) {
        hullPoints[j] = contourArray[hullContourIdxList[j]]
    }
    
    // 처음에 검출한 윤곽선 정보를 토대로 그리기
    Imgproc.drawContours(src, contours, i, RED)
    
    // 컨벡스 헐 정보를 토대로 그리기
    Imgproc.drawContours(src, listOf(MatOfPoint(*hullPoints)),0, GREEN)
    
    // 볼록결함 찾기
    val convexDefects = MatOfInt4()
    Imgproc.convexityDefects(contour, convexHull, convexDefects)
    val convexDefeatList = convexDefects.toList()
    val vertexArray = contour.toArray()
    for(j in 0 until convexDefeatList.size step 4){
        val start = vertexArray[convexDefeatList[j]]
        val end = vertexArray[convexDefeatList[j+1]]
   
        // 컨벡스 헐의 시작점(start)과 끝점(end) 사이의 볼록결함
        val def = vertexArray[convexDefeatList[j+2]]
        Imgproc.circle(src, def, 5, BLUE, 2)
    }
}
카테고리: OpenCV

0개의 댓글

답글 남기기

Avatar placeholder

이메일은 공개되지 않습니다. 필수 입력창은 * 로 표시되어 있습니다.