2010-08-06 4 views
1

나는이 코드에 눈을 보게 될 것이다. 그것은 일련의 데이터 포인트에 가장 잘 맞는 타원을 찾았습니다. 문제는 major & 보조 축 (aDist 및 bDist)의 길이가 예상보다 커지고 있다는 것입니다.가장 적합한 타원 코드의 버그

입력 :

  • 점 - (X, Y)의 세트는 데이터 포인트 좌표; x 및 y를 음수
  • avgX, avgY - 모든 데이터 포인트

출력의 x 및 y 좌표의 평균 :

  • aDist, bDist - 주요의 길이 및 작은 축
 // Find a and b -- use principal component analysis 
    // http://ask.metafilter.com/36213/Best-Fit-Ellipse (2nd reply) 
    // http://number-none.com/product/My%20Friend,%20the%20Covariance%20Body/index.html 

    double mat[2][2]; // Will be the covariance matrix. 
         // Eigenvectors will be major & minor axes. Eigenvalues will be lengths of axes, squared. 

    mat[0][0] = mat[0][1] = mat[1][0] = mat[1][1] = 0; 
    for (CPixelList::iterator i = points->begin(); i != points->end(); i++) 
    { 
     // Add [ x - avgX, y - avgY ] * [ x - avgX ] to mat 
     //        [ y - avgY ] 
     double diffX = i->x - avgX; 
     double diffY = i->y - avgY; 
     mat[0][0] += diffX * diffX; 
     mat[0][1] += diffX * diffY; 
     mat[1][1] += diffY * diffY; 
    } 
    mat[1][0] = mat[0][1]; 

    // http://www.math.harvard.edu/archive/21b_fall_04/exhibits/2dmatrices/index.html 
    double T = mat[0][0] + mat[1][1];       // Trace 
    double D = mat[0][0] * mat[1][1] - mat[0][1] * mat[1][0]; // Determinant 
    double L1 = T/2 + sqrt(T*T/4 - D);  // Eigenvalues 
    double L2 = T/2 - sqrt(T*T/4 - D);  // 
    aDist = sqrt(L1); 
    bDist = sqrt(L2); 

나는 디버거에서 입력을 확인하신 후, 그들은 확인을 보인다. 회전이없는 간단한 모양 (원, 타원, 사각형)에이 코드를 시도했지만 aDist와 bDist는 모양에 비례하지만 항상 너무 큽니다. 예를 들어, '포인트'aDist 및 bDist가 582

업데이트됩니다 다음, 100 × 100 원입니다 : 마이크가 제안 mat을 합산 한 후, 지금, points->size() 각 요소를 나눕니다. points이 < (0,0), (10,0), (10,10), (0,10)> 인 경우, aDistbDist은 이제과 같이 인 5가 너무 작습니다. 더 많은 픽셀이 사각형에 추가되면 aDistbDist이 작아집니다. 예를 들어, < (0,0), (5,0), (10,0), (10,5), (10,10), (5,10), (0,10))> 반경은 sqrt (18.75) = 4.33입니다.

답변

1

올바른 공분산 행렬을 얻으려면 총 포인트 수로 mat을 나눌 필요가 있습니다.

+0

감사합니다. 문제의 일부일 수도 있지만 ... 이제는 aDist 및 bDist가 너무 작습니다. 100x100 (반경 = 50) 원에 대해서는 35. – jlstrecker

+0

수정 이유는 모르겠지만 나머지 부분은 'aDist = sqrt (2 * L1)'및'bDist = sqrt (2)입니다. * L2)'. – jlstrecker