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)
}
}
0개의 댓글