Prerequisite : 윤곽선 길이 구하기

fitLine 함수

OpenCV에서는 fitLine이라는 함수를 제공하는데, 이는 주어진 점들을 적당히 감싸는 직선 정보를 구할 수 있다.

fitLine 함수는 ∑iρ(ri)를 최소화하여 2D 또는 3D 점들의 집합에 선을 피팅하는데, 여기서 ri는 i번째 점과 선 사이의 거리이고, ρ(r)은 거리를 구하는 함수다.

거리를 구하는 함수의 종류는 다음과 같다.

  • DIST_L2: ρ(r)=r2/2, 가장 간단하고 빠른 최소제곱법
  • DIST_L1: distance = |x1-x2| + |y1-y2|
  • DIST_C: distance = max(|x1-x2|,|y1-y2|)
  • DIST_L12: L1-L2 metric: distance = 2(sqrt(1+x*x/2) – 1))
  • DIST_FAIR: distance = c^2(|x|/c-log(1+|x|/c)), c = 1.3998
  • DIST_WELSCH: distance = c^2/2(1-exp(-(x/c)^2)), c = 2.9846
  • DIST_HUBER: distance = |x|<c ? x^2/2 : c(|x|-c/2), c=1.345

fitLine 함수의 매개변수에 대해서 살펴보자

Imgproc.fitLine(contour, line, distType, param, reps, aeps)

contour: 윤곽선 정보, 2D 또는 3D 좌표의 벡터값
line: 함수 호출 후 참조 가능한 Mat 타입의 선분 정보
distType: 거리를 구하는 함수 타입
param: 일부 distType에 대한 수치 매개변수( C ), 0이면 최적의 값이 선택된다.
reps: 반경에 대한 충분한 정확도(좌표 원점과 선 사이의 거리)
aeps: 각도에 대한 충분한 정확도. reps와 aeps에 대해 좋은 기본값은 0.01이다.

fitLine 함수를 통해 이미지내 윤곽선에 적합한 직선을 구하는 예제를 살펴보자.

원본이미지

예제코드:

val contours = ArrayList<MatOfPoint>()
val hierarchy = Mat()
// 윤곽선 좌표 구하기
Imgproc.findContours(
    binary,
    contours,
    hierarchy,
    Imgproc.RETR_CCOMP,
    Imgproc.CHAIN_APPROX_SIMPLE
)

for (i in 0 until contours.size) {
    val contour2f = MatOfPoint2f(*contours[i].toArray())
    val line = Mat()
    // 주어진 점들에 대해 적합한 선분 정보 구하기
    Imgproc.fitLine(contour2f, line, Imgproc.DIST_L2, 0.0, 0.01, 0.01)
    // 단위 벡터
    val vx = line.get(0, 0)[0]
    val vy = line.get(1, 0)[0]
    // 직선위의 점
    val x = line.get(2, 0)[0]
    val y = line.get(3, 0)[0]
    // 이미지 경계부근까지 연장한 후 빨간색으로 그림 
    val lefty = (-x * vy / vx + y).roundToInt().toDouble()
    val righty = ((src.cols() - x) * vy / vx + y).roundToInt().toDouble()
    val point1 = Point((src.cols() - 1).toDouble(), righty)
    val point2 = Point(0.0, lefty)
    Imgproc.line(src, point1, point2, RED)
}
카테고리: OpenCV

0개의 댓글

답글 남기기

Avatar placeholder

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