Dato un insieme di punti 2D (in forma cartesiana), ho bisogno di trovare l'ellisse dell'area minima in modo tale che ogni punto nell'insieme si trovi o all'interno o all'interno dell'ellisse .Come adattare un'ellisse di delimitazione attorno a un insieme di punti 2D
Ho found the solution sotto forma di pseudo-codice su questo sito, ma il mio tentativo di implementare la soluzione in C++ non ha avuto successo.
L'immagine seguente illustra graficamente ciò che la soluzione al mio problema si presenta come:
Nel mio tentativo, ho usato la biblioteca Eigen per le varie operazioni su matrici.
//The tolerance for error in fitting the ellipse
double tolerance = 0.2;
int n = 10; // number of points
int d = 2; // dimension
MatrixXd p = MatrixXd::Random(d,n); //Fill matrix with random points
MatrixXd q = p;
q.conservativeResize(p.rows() + 1, p.cols());
for(size_t i = 0; i < q.cols(); i++)
{
q(q.rows() - 1, i) = 1;
}
int count = 1;
double err = 1;
const double init_u = 1.0/(double) n;
MatrixXd u = MatrixXd::Constant(n, 1, init_u);
while(err > tolerance)
{
MatrixXd Q_tr = q.transpose();
cout << "1 " << endl;
MatrixXd X = q * u.asDiagonal() * Q_tr;
cout << "1a " << endl;
MatrixXd M = (Q_tr * X.inverse() * q).asDiagonal();
cout << "1b " << endl;
int j_x, j_y;
double maximum = M.maxCoeff(&j_x, &j_y);
double step_size = (maximum - d - 1)/((d + 1) * (maximum + 1));
MatrixXd new_u = (1 - step_size) * u;
new_u(j_x, 0) += step_size;
cout << "2 " << endl;
//Find err
MatrixXd u_diff = new_u - u;
for(size_t i = 0; i < u_diff.rows(); i++)
{
for(size_t j = 0; j < u_diff.cols(); j++)
u_diff(i, j) *= u_diff(i, j); // Square each element of the matrix
}
err = sqrt(u_diff.sum());
count++;
u = new_u;
}
cout << "3 " << endl;
MatrixXd U = u.asDiagonal();
MatrixXd A = (1.0/(double) d) * (p * U * p.transpose() - (p * u) * (p * u).transpose()).inverse();
MatrixXd c = p * u;
L'errore si verifica nella seguente riga:
MatrixXd M = (Q_tr * X.inverse() * q).asDiagonal();
e si legge come segue:
run: /usr/include/eigen3/Eigen/src/Core/DenseBase.h:261: void Eigen::DenseBase<Derived>::resize(Eigen::Index, Eigen::Index) [with Derived = Eigen::Diagonal<Eigen::Matrix<double, -1, -1>, 0>; Eigen::Index = long int]: Assertion `rows == this->rows() && cols == this->cols() && "DenseBase::resize() does not actually allow to resize."' failed.
Aborted (core dumped)
Qualcuno può sottolineare perché questo errore si verifica o, meglio ancora, danno qualche consiglio su come adattare un'ellisse a un insieme di punti usando C++?
Questo risolve interamente il problema e l'algoritmo trova l'ellisse. Sembra che il problema sia dovuto alla mia mancanza di comprensione dell'algebra lineare piuttosto che del C++. Grazie! – Dziugas