'Fitting Algorithm'에 해당되는 글 5건

  1. 2012.10.07 RANSAC Ellipse Fitting
  2. 2008.07.21 RANSAC : Circle Fit
  3. 2008.07.08 Robust Line Fitting
  4. 2008.06.29 EM Algorithm : Line Fitting 예
  5. 2008.05.24 RANSAC Algorithm

다섯개의 점들 (x1,y1), (x2,y2), (x3,y3), (x4,y4), (x5,y5)에 대해서 conic eq의 왼쪽값(대수적인 거리^2)이 최소가 되도록 하는 conic parameter를 결정하는 식은 다음과 같다: 

이 식은 해는 다음의 방정식을 만족시키는 해를 구하는 것과 같다:

또는 행렬식으로 표현하면,

의 형태로 쓰여진다. 6개의 conic-parameters를 결정해야 하므로, A는 마지막 행을 0으로 채워서 6x6 행렬로 만들어서 사용한다.  따라서 A(->A6x6)는 singular 행렬이 된다. A를 다음과 같이 singular value decomposition(SVD)를 할 때

가장 작은 eigenvalue(w)에 해당하는 V의 열벡터가 에러를 최소로 하는 conic parameter를 준다 (행렬 V의 각 열들이 6차원 벡터공간의 기저를 형성한다. U는 orthogonal 행렬이어서 오른쪽에서 곱해지는 벡터의 크기를 변화시키지 않고 단지 회전만 시킨다. 따라서 가장 작은 고유값에 해당하는 V의 열벡터가 |A.x|를  최소화시킨다)



// 주어진 점에서 타원까지의 대수적 거리: conic-eq의 좌변의 값;

static double fitting_error(double conic_params[6], double x, double y) {

더보기

//

static int ransac_sample_number(int ndata, int ngood, double prob, int ntry) {

더보기

int ransac_ellipse_fitter(std::vector<CPoint>& points, int width, int height,

                          double ellipse_params[5],/*(a, b, cx, cy, theta)*/

                          std::vector<int> &best_index)

{

    const int npts = points.size(); 

    if (npts < 5) {

        return 0;

    }

    // 안정적인 conic fitting을 위해서 데이터를 (-1,1)구간으로 normalize함;

    std::vector<CfPt> nor_pts(npts);

    double ellipse_scale; //원점에서  타원점들까지의 평균거리;

    CfPt ellipse_center;  //타원의 중심 예측;

    normalize_points(points, nor_pts, &ellipse_scale, &ellipse_center);

    //

    std::vector<int> inliers_index(npts);

    best_index.resize(npts);

    // inverse_scale을 기준으로 만들어졌음;

    const double dist_threshold = sqrt(3.84) / ellipse_scale;

    double best_params[5];

#define MAX_ITERATION (1500)

    int sample_num = 1000; //number of sample

    int ransac_iter = 0;

    int max_inliers = 0;

    while (sample_num > ransac_iter) {

        int rand_idx[5];

        //5 점을 랜덤하게 선택;

        random_quintet((npts - 1), rand_idx);

  //5 점을 이용해서 conic parameter estimate;

double conic_params[6];

get_conic_params(nor_pts, rand_idx, conic_params);


        //conic parameter를 이용해서 inlier후보들을 모음;

        int ninliers = 0;

        for (int i = 0; i < npts; i++) {

            double error = fitting_error(conic_params, nor_pts[i].x, nor_pts[i].y);

            if (fabs(error) < dist_threshold) {

                inliers_index[ninliers] = i;

                ninliers++;

            }

        }


        if (ninliers > max_inliers) {

            if (conic_to_ellipse(conic_params, ellipse_params)) {

                get_real_params(ellipse_params, ellipse_scale, ellipse_center, ellipse_params);

                // 주어진 영역안의 정상적인 타원만 선택함;

                if (regular_ellipse(ellipse_params, width, height, 0.5, 2.0)) {

                    max_inliers = ninliers;

                    //이 단계에서 inliers를 이용해서 다시 타원을 예측한다;

                    //if (ninliers >= 6) {

                    // std::vector<double> pts(2 * ninliers);

                    // for (int i = 0; i < ninliers; i++) {

                    // pts[2 * i + 0] = points[inliers_index[i]].x ;

                    // pts[2 * i + 1] = points[inliers_index[i]].y ;

                    // }

                    // EllipseFit(&pts[0], ninliers, conic_params);

                    // for (int i = 0; i < 5; i++) best_params[i] = conic_params[i];

                    //}

                    // if (ninliers == 5) 

                    for (int i = 0; i < 5; i++) best_params[i] = ellipse_params[i];

                    for (int i = 0; i < ninliers; i++) best_index[i] = inliers_index[i];

                    sample_num = ransac_sample_number(npts, ninliers, 0.99, 5);

                }

            }

        }

        ransac_iter++;

        if (ransac_iter > MAX_ITERATION) {

            TRACE("Error! ransac_iter exceeds!\n");

            max_inliers = 0;

            break ;

        }

    }


    if (best_params[0] > 0 && best_params[1] > 0)

        for (int i = 0; i < 5; i++) ellipse_params[i] = best_params[i];

    else

        max_inliers = 0;


    best_index.resize(max_inliers);

    return best_index.size();

}

저작자 표시 비영리 변경 금지
신고
크리에이티브 커먼즈 라이선스
Creative Commons License
Posted by helloktk

RANSAC 알고리즘을 이용하여서 원을 추정한다. 원을 만들기 위해서는 최소한 3개의 일직선상에 있지 않은 점을 잡아야 하면, 이때 원은 세점의 외접원으로 주어진다. 이 원을 기본으로 해서 다시 원의 중심과 반지름을 추정한다. 추정된 원들 중에서 inlier 들의 벗어남의 편차가 가장 작은 것을 결과로 이용한다.
// 참고: http://en.wikipedia.org/wiki/RANSAC 
//

// [0,max_num) 사이에서 3개의 숫자를 무작위로 선택함;
void GetRandomTriplet(int max_num, int triplet[3]) {

더보기

// 세 점의 외접원을 구함;
int CircumCircle(double x1, double x2, double x3,
                 double y1, double y2, double y3,
                 double *cx, double *cy, double *rad) {

더보기

// 3x3 선형방정식을 푼다: A * x = b;
bool SolveLinearEQ3x3(double A[9], double bb[3], double x[3]) {

더보기

// x^2 + y^2 + A*x + B*y + C = 0;
// Least square fit for A, B, C;
int CircleFit_LS(int N, double xp[], double yp[],
                   double *cx, double *cy, double *rad) {  

더보기

// 데이터 중에서 주어진 원에서 거리 임계값 이내의 데이터만 골라냄;
int findInlier(double xp[], double yp[], int N,
                double cx, double cy, double rad,
                double dist_th,
                double consensusx[], double consensusy[], double *var) {

더보기

int RansacCircleFit(int N, double xp[], double yp[],
                    int sample_th,      //# of inliers; >= 50% of data(N), 66%;
                    double dist_th,     // 25% of radius;   |dist-rad|/rad< dist_th
                    int max_iter,
                    double *centerx,
                    double *centery,
                    double *radius)
{    
    double pr = double(sample_th) / double(N);
    double trials99 = log(1. - 0.99)/log(1. - pow(pr, 3));
    double tx[3], ty[3];
    int tri[3];
    int found = 0;  
    int iter = min(max_iter, trials99);
    //inlier buffer;
    std::vector<double> consensusx(N), consensusy(N) ;
    double min_dev = 1.e+10, var, sdev;
    if (sample_th < 3) sample_th = 3;
    while (iter) {
        GetRandomTriplet(N, tri);
        for (int i = 0; i < 3; i++) {
            tx[i] = xp[tri[i]];
            ty[i] = yp[tri[i]];
        }
        double cx, cy, rad;
        if (!CircumCircle(tx[0], ty[0], tx[1], ty[1], tx[2], ty[2], &cx, &cy, &rad)) {
            // if tree points are degenerate or on the sample line, discard them!
            continue ;
        }
        int ninlier = findInlier(xp, yp, N, cx, cy, rad, dist_th, &consensusx[0], &consensusy[0], &var);
        if (ninlier >= sample_th) {          
            // estimate model params using maybe-inliers;
            if (!CircleFit_LS(ninlier, &consensusx[0], &consensusy[0], &cx, &cy, &rad))
                continue; //least-square fitting fails;
            // collect real-inliers;
            ninlier = findInlier(xp, yp, N, cx, cy, rad, dist_th / 2, &consensusx[0], &consensusy[0], &var);
            if (ninlier < sample_th)
                continue;
            sdev = sqrt(var / ninlier);
            // estimate model params using inliers again;
            if (!CircleFit_LS(ninlier, &consensusx[0], &consensusy[0], &cx, &cy, &rad))
                continue;            
            TRACE("cx = %f, cy = %f, rad=%f\n", cx, cy, rad);
            if (sdev < min_dev) {
                *centerx = cx;
                *centery = cy;
                *radius  = rad;
                min_dev = sdev;
                found = 1;
                // we need more elaborate termination conditions;
#if _DEBUG
#endif
            }
        }
        --iter;
    }
    return found;
};

  • sample_th = 2 * N / 3;
  • dist_deviate_th = 0.25;
  • 파란색: 최소자승법을 이용한 피팅 (outlier의 영향을 많이 받음);
  • 붉은색: RANSAC 피팅 결과 (2017.01.04 수정)


see also http://blog.naver.com/helloktk/80029898273


신고
크리에이티브 커먼즈 라이선스
Creative Commons License

'Image Recognition' 카테고리의 다른 글

Chamfer Match  (0) 2008.08.01
Retinex Algorithm  (1) 2008.07.26
RANSAC : Circle Fit  (0) 2008.07.21
KMeans Algorithm  (0) 2008.07.19
Robust Line Fitting  (0) 2008.07.08
Bayesian Spam Filtering  (0) 2008.07.03
Posted by helloktk

이미지에서 관찰된 점들이 {(xi, yi) | i = 1, 2,..., N}이 있다. 이 점들을 직선 y = a + b*x 로 피팅을 하고 싶을 때, 보통 최소 자승법을 이용하는 데,  원리는 직선의 방정식이 예측한 y값과 실제 관찰한 y값의 차이의 제곱(=square deviation)을 최소화시키는 직선의 파라미터 a, b를 찾는 것과 동일하다:


확률적으로는, 데이터를 얻는 과정인 측정에서 측정값 yi 는 랜덤에러를 가지게 되고, 이 에러는 참값 y(x) 근방에서 정규분포의 모양을 가지게 된다고 가정을 한다. 만약에 모든 측정의 에러가 동일한 표준편차 σ를 갖게 된다면, N개의 관측데이터가 나타날 확률(likelihood)는 (개별측정은 IID조건을 만족한다고 전제)
     

의 형태가 된다. 따라서 최소자승방법은 이 likelihood를 최대화시키는 파라미터를 찾는 방법이 된다. 이 최소 자승법은 피팅 파라미터를 주어진 데이터를 이용해서 표현할 수 있는 장점이 있지만, outliers에 대해서 매우 취약하다 (아래의 결과 그림을 참조). 이것은 적은 수의 outlier도 χ2 에 큰 기여를 할 수 있기 때문이다. 따라서 피팅을 좀더 robust하게 만들기 위해서는 이들 outlier들이 likelihood에 기여하는 정도를 줄여야 한다. 그러기 위해서는 likelihood의 지수인자가 큰 에러에서 덜 민감하게 반응하는 꼴로 바뀌어야 한다. 이런 형태 중에서 가장 간단한 것 중의 하나가 square deviation 대신에 absolute deviation을 이용하는 것이다:


그러나 이 식을 이용하는 경우에는 최소자승법과는 달리, 파라미터 a, b를 주어진 데이터 {(xi, yi)}로 표현할 수 없고, 반복적인 방법을 이용해서 찾는 수 밖에 없다. 


주어진 수열 {c
i}와 a 와의 차이의 절대값의 합
i |ci - a| 는 a가 이 수열의 median 값인 경우에 최소된다는 사실을 이용하면 (증명: 극값을 구하기 위해서 a에 대해서 미분하면, 0 = (i 1) - (i 1) : 합은 a가 ci 보다 큰 경우와 작은 경우로 분리=> 따라서 0이 되기 위해서는 작은 경우와 큰 경우의 수가 같아야 한다 => 즉, a = median{ci}), 고정된 b값에 대해서 위 absolute deviation을 최소화 시키는 a값은

 


임을 알 수 있다. 그리고 absolute deviation 식을 b에 대해서 미분을 하여서


을 얻는데 위의 a 값을 대입해서 위의 식을 만족시키는 b값을 bracketing and bisection 방법을 이용해서 얻을 수 있다(불연속함수여서, 일반적으로 근을 구하는 방법을 사용하는 것은 위험하다). 아래의 코드는 이를 구현한 것이다.


참고 : Numerical Recipes. 

// qsort-comparator; 

static int comp(const void *a, const void * b) { 

    double d = *((double *)a) - *((double *)b);

    return d > 0 ? 1 : d < 0 ? -1 : 0; 

// 기울기(bb)가 주어진 경우에 y-절편(median = aa)값을 추정하고, 이 때 AD값을 얻는다. 

double RhoFunc(double *x, double* y, int n, 

               double bb, double *aa, double *abdev) { 

    double *h = new double [n];

    for (int i = 0; i < n; i++)  h[i] = y[i] - bb * x[i];

    qsort(h, n, sizeof(double), comp); 

    // median; 

    *aa = (n & 1) ? h[n / 2] : (h[n / 2] + h[n / 2 - 1]) / 2;

    

    double sum = 0;  

    *abdev = 0; 

    for (i = 0; i < n; i++) { 

        double d = y[i] - (bb * x[i] + (*aa)); 

        *abdev += fabs(d); 

        // sign-함수의 원점에서 모호함을 없애기 위해서 증폭을 시킴; 

        if (y[i] != 0.) d /= fabs(y[i]);

        if (fabs(d) > DBL_EPSILON) // sign 함수의 모호함에서 벗어나면,

            sum += (d >= 0 ? x[i] : -x[i]); 

    } 

    delete [] h;

    return sum; // return sum{xi * sign(yi - (b * xi + a))} 

}; 

// 최소자승법을 이용한 라인추정: 

// return (sigma[dy] / sigma[x]);

double FitLine_LS(double *x, double *y, int n, double *a, double *b) { 

    double sx = 0, sy = 0, sxx = 0, sxy = 0; 

    for (int i = 0; i < n; i++) { 

        sx += x[i]; 

        sy += y[i]; 

        sxx += x[i] * x[i] ; 

        sxy += x[i] * y[i] ; 

    }; 

    double det = n * sxx - sx * sx; 

    if (det == 0.) return -1;                   // vertical line;

    *a = (sxx * sy - sx * sxy) / det; 

    *b = (n * sxy - sx * sy) / det;  

    double chi2 = 0;  

    for (i = 0; i < n; i++) { 

        double t = y[i] - (*a + *b * x[i]); 

        chi2 += t * t; 

    }  

    det /= n; // det -> var(x) * n; 

    // chi2 = var(dy) * n;

    // (dy vs x의 편차비)

    return  sqrt(chi2 / det);  ; 

}

// y = a + b * x ; 

// Least Absolute Deviation: 

void FitLine_MAD (double *x, double *y, int n, 

                  double *a, double *b, double *mad) 

    // least square esimates for (aa, bb);      

    double aa, bb; 

    double sigb = FitLine_LS(x, y, n, &aa, &bb); 

    double b1 = bb; 

    double abdev; 

    double f1 = RhoFunc(x, y, n, b1, &aa, &abdev); 

    /* bracket 3-sigma away in the downhill direction; */ 

    double b2 = fabs(3 * sigb); 

    b2 = bb + (f1 < 0 ? -b2 : b2); 

    double f2 = RhoFunc(x, y, n, b2, &aa, &abdev); 

    

    // if conditional added to take care of the case of a

    // line input into this function. It is needed to avoid an

    // infinite loop when (b1 == b2) (within floating point error)

    if (fabs(b2 - b1) > (sigb + 0.005)) { 

        // bracketing;

        while ((f1 * f2) > 0) { 

            bb = 2 * b2 - b1; 

            b1 = b2;

            b2 = bb;

            f1 = f2;  

            f2 = RhoFunc(x, y, n, b2, &aa, &abdev) ; 

        } 

    } 

    // refine until the error is a negligible number of std; 

    sigb *= 0.01; 

    while (fabs(b2 - b1)> sigb) { 

        // bisection; 

        bb = (b1 + b2) / 2.; 

        if ((bb == b1) || (bb == b2)) break ; 

        double f = RhoFunc(x, y, n, bb, &aa, &abdev) ; 

        if ((f * f1) >= 0) { 

            f1 = f; 

            b1 = bb; 

        } 

        else { 

            f2 = f; 

            b2 = bb; 

        } 

    } 

    *a = aa; 

    *b = bb; 

    *mad = abdev / n; 

}

// 붉은 선--> 최소자승법에 의한 피팅.: outlier에 매우 취약한 구조.
// 파란 선--> least absolute deviation을 이용한 피팅: outlier에 매우 robust하다.

"사용자

신고
크리에이티브 커먼즈 라이선스
Creative Commons License

'Image Recognition' 카테고리의 다른 글

RANSAC : Circle Fit  (0) 2008.07.21
KMeans Algorithm  (0) 2008.07.19
Robust Line Fitting  (0) 2008.07.08
Bayesian Spam Filtering  (0) 2008.07.03
EM : Binarization  (0) 2008.07.01
EM Algorithm : Line Fitting 예  (0) 2008.06.29
Posted by helloktk

아래의 그림을 보면 우리는 데이터를 연결하는 두 개의 직선을 생각할 수 있을 것이다.  그럼 두개의 직선을 어떻게 얻을 것인다? 물론, ICA 를 이용하는것이 한가지 방법이 될 것이다. 여기서는 EM 알고리즘을 이용하여서 두개의 직선을 기술하는 기울기와 y-절편의 값을 구하는 방법을 알아본다.

사용자 삽입 이미지


두 개의 직선을 각각 y=a1 * x + b1 , y = a2 * x + b2,라고 하면, 문제는 (a1, b1), (a2, b2)를 찾는 구하는 문제이다. 만약에 각각의 data 점의 측정에 의한 에러분포가 정규분포를 따른다면(여기서는 두 개의 모델 모두 갖은 표준편차를 갖는다고 가정했다) i-번째의 데이터 점이 각각의 직선모델1 과 2에 속할 확률은 (posterior with equal prior) 베이즈 공식에 의해서 

로 주어진다. 여기서 r1(i)와 r2(i)는 residual error이다:

(*이 값 대신에 직선에서의 거리=로 대체하여도 된다)

이제 각각의 데이터에 대해서 posterior를 구하였으므로(E-step) 이 값을 가중치로 하여서 직선의 방정식을 다시 갱신한다. 즉, 각각의 data 점들에 대한 w1(i)를 가중치로 하여서 다시 직선모델1의 파라미터를 재계산하고, 동일한 과정을 w2(i)를 가지고 직선모델2를 계산하여서 (a1,b1), (a2, b2)를 재계산한다(M-step). 이 갱신된 파라미터를 이용하여서 다시 가중치를 구하는 작업과, 직선의 파라미터를 구하는 작업을 일정하게 수렴할 때까지 반복을 하는 과정을 취하면 된다.

아래의 그림은 3번만에 원하는 결과를 얻는 것을 보여준다. 직선의 파라미터에 대한 초기값과 residual error의 표준편차 파리미터에 대한 적절한 값의 선택은 중요하다.

사용자 삽입 이미지

//코드의 일부...
std::vector<CPoint> data ;                                         // data,
std::vector<double> w1(data.size()), w2(data.size());  // weights.
double a1, b1, a2, b2 ;                                              // line params;
double sigma ;
// E-step;
void calcWeights() {
    for(int i=0; i<data.size(); i++){
        double  x = data[i].x,
                y = data[i].y ;
        double r1 = a1 * x + b1 - y ;
        double r2 = a2 * x + b2 - y ;
        double n1 = SQR(r1) / SQR(sigma);
        double n2 = SQR(r2) / SQR(sigma);
        double p1 = exp( - n1);
        double p2 = exp( - n2);
        w1[i] = p1 / (p1 + p2);
        w2[i] = p2 / (p1 + p2);
    }
};
//  M-step
void estimModels() {
    double s1xx=0, s1x=0, s1=0, s1y=0, s1xy=0;
    double s2xx=0, s2x=0, s2=0, s2y=0, s2xy=0;
    for(int i=0; i<data.size(); i++){
        double  x = data[i].x,
                y = data[i].y ;
            s1xx += w1[i] * SQR(x);
            s1xy += w1[i] * x * y;
            s1x  += w1[i] * x ;
            s1y  += w1[i] * y ;
            s1   += w1[i];
            //
            s2xx += w2[i] * SQR(x) ;
            s2xy += w2[i] * x * y ;
            s2x  += w2[i] * x ;
            s2y  += w2[i] * y ;
            s2   += w2[i];
    };
    double det1=s1xx*s1 - SQR(s1x);
    double det2=s2xx*s2 - SQR(s2x);
    a1 =(  s1 * s1xy  - s1x * s1y )/det1 ;
    b1 =(  s1xx * s1y - s1x * s1xy)/det1 ;
    a2 =(  s2 * s2xy  - s2x * s2y )/det2 ;
    b2 =(  s2xx * s2y - s2x * s2xy)/det2 ;
}

신고
크리에이티브 커먼즈 라이선스
Creative Commons License

'Image Recognition' 카테고리의 다른 글

Bayesian Spam Filtering  (0) 2008.07.03
EM : Binarization  (0) 2008.07.01
EM Algorithm : Line Fitting 예  (0) 2008.06.29
Shuffling  (0) 2008.06.21
Bayesian Decision Theory  (1) 2008.06.17
Gaussian Mixture Model  (2) 2008.06.07
Posted by helloktk

어떤 현상을 설명하는 이론 모델을 만들고자 하면 현상에서 관측데이터를 모아야한다. 그런데 관측 데이터에는 모델에 대한 잘못된 가정이나 측정장비의 오차등에서 생기는 여러가지 형태의 노이즈가 들어있게 마련이다. 이러한 노이즈는 모델을 정확히 예측하는 것을 방해한다. 이처럼 모델파라미터의 예측을 방해하는 데이터(outliner)가 들어 있는 관측데이터로부터 어떻게 하면 모델을 구축할 수 있는가라는 질문에 대한 한 대답을 RANSAC ("RANdom SAmple Consensus")  알고리즘이 제공한다. 이 알고리즘은 1981년 Fischler 과Bolles에 의해서 제안되었다.

RANSAC 알고리즘에 들어가는 입력은 관측된 데이터값과, 관측결과를 피팅하거나 설명할 수 있는 모델파라미터, 그리고 신뢰성을 나타내는 파라미터를 필요로 한다.

RANSAC알고리즘은 주어진 원본데이터에서 반복적으로 일부를 임의로 선택하는 과정을 반복하여서 최적의 파라미터를 예측하는 프로시져의 형태를 가진다. 전체의 관측데이터가 M개 있고, 모델파라미터를 예측하는데 N개의 데이터가 필요한 경우에, 알고리즘은 :

     1. 임의로 관측데이터에서 N개의 서브데이터를 선택한다.
     2. 이 데이터를 (가상의) inlier로 생각하고 모델을 예측한다.
     3. 원본데이터중에서 예측된 모델에 잘 맞는가를 체크한다. 잘 맞는 데이터 수를 K라고 한다.
     4. 만약에 K가 충분하면, 이 모델을 확정하고 알고리즘을 종료한다.
     5. 모델이 좋지 않으면 1-->4과정을  L 번  반복한다.
     6. 충분히 반복후에도 좋은 모델을 찾지 못하면 모델예측에 실패한 것으로 간주한다.

1. 임계값 K 는 모델이 얼마나 잘 맞는가에 대한 사용자입력으로부터 결정이 된다. 그러나 대략적으로 주어진 샘플에서 inlier의 비율 Pg 이라고 생각되는 정도를 잡으면 된다 :
 
   K = M * (1- P
g)

2. 얼마나 많은 반복을 해야하는가? 주어진 관측데이터에서 inlier일 확률이 Pg인 경우에 L번의 모델예측시도가 실패할 확률을 계산하여서 이것이 주어진 설정값, pfail 보다도 작은 경우에 모델예측의 실패로 처리하므로,

  pfail   = L번의 모델예측 실패확률
          = (한번 시도가 실패할 확률)L
          = (1 - 한번 시도가 성공할 확률))L
          = (1 - (랜덤데이터가 모델을 예측할 확률)N))L
          = (1- (Pg) N)L

이 사실로 부터 최대 반복횟수는 
    
   L = log(pfail)/log(1-(Pg)N)

로 주어진다.
inlier가 반이 섞인 경우 Pg (=주어진 데이터중에서 inlier일 확률)
= 0.5,
p
fail = 0.01 인 경우, 만약에, N = 3 (세 점만 있으면 모델구성이 가능한 원의 피팅이 한 예임) 일 때, 최대 반복횟수는 윗 식에 적용하면,
     
                   L = 35 회


RANSAC알고리즘은 주어진 관측데이터에 많은 outlier가 존재하더라도 매우 정확히 모델파라미터를 예측할 수 있는 능력이 있는 robust한 알고리즘이지만, 얼마나 많은 반복을 해야하는가에 대한 상한값이 제공되지 않는다(사용자가 pfail 를 설정한다). 따라서 사용자 설정에 의한 상한값은 최적의 모델이 아닐 수 있다.

"The RANSAC procedure is opposite to that of conventional smoothing techniques: Rather than using as much of the data as possible to obtain an initial solution and then attempting to eliminate the invalid data points, RANSAC uses as small an initial data set as feasible and enlarges this set with consistent data when possible".

Martin A. Fischler and Robert C. Bolles (June 1981). "Random Sample Consensus: A Paradigm for Model Fitting with Applications to Image Analysis and Automated Cartography". Comm. of the ACM 24: 381–395.

예제코드:
ransac을 이용한 라인 피팅: http://blog.naver.com/helloktk/80029006029
ransac을 이용한 원 피팅: http://kipl.tistory.com/32

신고
크리에이티브 커먼즈 라이선스
Creative Commons License

'Image Recognition' 카테고리의 다른 글

Gaussian Mixture Model  (2) 2008.06.07
Rasterizing Voronoi Diagram  (0) 2008.05.26
RANSAC Algorithm  (0) 2008.05.24
Contour Tracing  (0) 2008.05.22
Gausssian Scale Space  (0) 2008.05.22
Watershed Algorithm 적용의 예  (2) 2008.05.21
Posted by helloktk


티스토리 툴바