2010-08-06 48 views
1

我希望在此代碼中增加一組額外的眼睛。它應該爲一組數據點找到最適合的橢圓。問題是短軸(aDist和bDist)主要長度比他們應該大。最適合的橢圓代碼中的錯誤

輸入:

  • 點 - 一組(X,Y)座標數據點; x和y都是非負
  • 平均值x,平均值y - 所有數據點

輸出的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); 

我已經檢查在調試器中輸入,他們看起來OK。我已經嘗試了一些簡單的形狀(圓形,橢圓形,矩形)的代碼,沒有旋轉,而aDist和bDist與形狀成正比,但總是太大。例如,如果「點」是一個100x100的圓圈,然後aDist和bDist是582

更新:總結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),(0,5 )>給出半徑sqrt(18.75)= 4.33。

回答

1

您需要將mat除以總點數得到正確的協方差矩陣。

+0

謝謝 - 這可能是問題的一部分......但現在aDist和bDist太小了。對於100x100(半徑= 50)的圓圈,它們是35. – jlstrecker 2010-08-07 03:59:22

+0

雖然我不明白爲什麼,但修正的另一半是: 'aDist = sqrt(2 * L1)'和'bDist = sqrt(2 * L2)'。 – jlstrecker 2010-08-08 14:28:09