我很欣赏这段代码。它应该为一组数据点找到最合适的椭圆。问题是主要和长度的长短。短轴(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)>,那么aDist
和bDist
是现在5,如预期的那样太小了。随着向该方块添加更多像素,aDist
和bDist
会变小。例如,<(0,0),(5,0),(10,0),(10,5),(10,10),(5,10),(0,10),(0, 5)>给出半径为sqrt(18.75)= 4.33。
答案 0 :(得分:1)
您需要将mat
除以总点数才能获得正确的协方差矩阵。