2011/11/21

[OpenCV] cvFitLine 사용하기

OpenCV 에서는 2D와 3D 데이터에 대한 Fitting 함수로 cvFitLine 함수를 제공 한다. cvFitLine 함수는 OpenCV 문서상 설명은 아래와 같이 되어있다.



FitLine

Fits line to 2D or 3D point set



void  cvFitLine( const CvArr* points, int dist_type, double param,
                 double reps, double aeps, float* line );

points

     Sequence or array of 2D or 3D points with 32-bit integer or floating-point coordinates.

dist_type

     The distance used for fitting (see the discussion).

param

     Numerical parameter (C) for some types of distances, if 0 then some optimal value is chosen.

reps, aeps

     Sufficient accuracy for radius (distance between the coordinate origin and the line) and angle, respectively, 0.01 would be a good defaults for both.

line

     The output line parameters. In case of 2d fitting it is array of 4 floats (vx, vy, x0, y0) where (vx, vy) is a normalized vector collinear to the line and (x0, y0) is some point on the line. In case of 3D fitting it is array of 6 floats (vx, vy, vz, x0, y0, z0) where (vx, vy, vz) is a normalized vector collinear to the line and (x0, y0, z0) is some point on the line.

The function cvFitLine fits line to 2D or 3D point set by minimizing sumiρ(ri), where ri is distance between i-th point and the line and ρ(r) is a distance function, one of:



dist_type=CV_DIST_L2 (L2):

ρ(r)=r2/2 (the simplest and the fastest least-squares method)



dist_type=CV_DIST_L1 (L1):

ρ(r)=r



dist_type=CV_DIST_L12 (L1-L2):

ρ(r)=2?[sqrt(1+r2/2) - 1]



dist_type=CV_DIST_FAIR (Fair):

ρ(r)=C2?[r/C - log(1 + r/C)],  C=1.3998



dist_type=CV_DIST_WELSCH (Welsch):

ρ(r)=C2/2?[1 - exp(-(r/C)2)],  C=2.9846



dist_type=CV_DIST_HUBER (Huber):

ρ(r)= r2/2,   if r < C

      C?(r-C/2),   otherwise;   C=1.345



하지만 문서상 어디에도 어떻게 사용하는지 설명이 되어 있지 않다.

인터넷에서 찾아 아래와 같은 결론에 이르렀다.

int nStart = (ptStart.y < ptEnd.y)? ptStart.y: ptEnd.y;
int nEnd = (ptStart.y > ptEnd.y)? ptStart.y: ptEnd.y;

int nCount = 0;
for ( int row = nStart; row < nEnd; ++row )
{
CvPoint2D32f p;
p.x = (float)nCount++;
p.y = m_pfData[ row * nWidth + ptStart.x ];
cvSeqPush( seq, &p );

TRACE("%.6f\n", p.y);
}

float fLine[4];
cvFitLine( seq, CV_DIST_L1, 1, 0.01, 0.01, fLine );
TRACE("Line > %.6f, %.6f, %.6f, %.6f\n",fLine[0] ,fLine[1],fLine[2],fLine[3]);

float fSlope = fLine[1] / fLine[0];
float fIntercept = fLine[3] - fSlope * fLine[2];





위 코드는 cvFitLine 을 사용한 일부분이다.

2D 데이터에 의한 Fitting을 하기 위해 32비트 Float 형식의 CvPoint2D32f 를 사용하였다.

데이터를 저장하기위한 메모리를 만들고 (cvCreateMemStorage) 시퀀스를 생성하였다. 그리고 Fitting에 필요한 데이터를 시퀀스에 담는다.

두 번째 인자는 Fitting 방법으로 거리 계산 방법인데 이에 대한 자세한 것은 아직 모르겠다. 세 번째는 두 번째 인자에서 지정한 거리 계산방법에 사용할 상수를 정하는 것으로 몇몇 거리계산 방법에는 적용되지 않는 것으로 보인다.  네 번째와 다섯 번째는 직선을 구하는 정확도를 의미하며 OpenCV 문서에서는 0.01로 지정하도록 권장하고 있다.



함수의 결과는 2D Fitting의 경우 결과 값으로 4개의 float 데이터가 반환된다.

두 개 단위로 값이 의미를 갖는데 첫 번째 두 개는 직선과 평행한  정규화된 벡터이고 다음 두 개는 이 벡터의 연장선상에 존재하는 한 점의 좌표를 의미한다.


3D Fitting에 대해서는 좀 더 공부를 해 봐야겠다.<

Original Post : http://neodreamer-dev.tistory.com/617

No comments :

Post a Comment