我希望对此代码多加关注。应该为一组数据点找到一个最合适的椭圆。问题是长轴和短轴(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与形状成比例,但总是太大。例如,如果“点”是100x100的圆圈,则aDist和bDist为582。
更新:总结了
mat
之后,我现在按照Mike的建议将每个元素除以points->size()
。如果points
是平方,则aDist
和bDist
现在为5,这与预期的太小了。随着向该正方形添加更多像素,aDist
和bDist
变小。例如,给出sqrt(18.75)= 4.33的半径。 最佳答案
您需要将mat
除以总点数以获得正确的协方差矩阵。
关于c++ - 最佳椭圆代码中的错误,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/3427309/