最合适的椭圆代码中的错误

时间:2010-08-06 19:58:30

标签: c++

我很欣赏这段代码。它应该为一组数据点找到最合适的椭圆。问题是主要和长度的长短。短轴(aDist和bDist)比它们应该更大。

输入:

  • points - 数据点的一组(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与形状成比例但总是太大。例如,如果'points'是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 个答案:

答案 0 :(得分:1)

您需要将mat除以总点数才能获得正确的协方差矩阵。