2016-06-19 21 views
6

2d puanlık bir set verildiğinde (Kartezyen formda), minimum alan elipsini bulmalıyım, böylece kümedeki her nokta ya elipsin üzerinde ya da içinde yatar. .Sınırlı bir elipsin bir dizi 2B nokta etrafına nasıl sığdırılır

Bu sitede sözde kod biçiminde found the solution32 var, ancak C++ çözümünü uygulama girişimi başarısız oldu. Benim girişimde

a set of points with a bounding ellipse

, ben matrisleri üzerinde çeşitli işlemler için Eigen kütüphane kullandı:

Aşağıdaki resim gibi benim sorunun çözümü göründüğünü grafiksel göstermektedir.

//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; 

hata aşağıdaki satırda oluşur:

MatrixXd M = (Q_tr * X.inverse() * q).asDiagonal(); 

ve aşağıdaki gibi okur:

birisi bu hata daha iyi oluşmasını veya neden işaret misiniz vermek

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) 
bana bir elipsin C++ kullanarak nasıl bir noktaya sığdırılacağına dair tavsiyem var mı?

cevap

1

Öz ile, .diagonal() ile bir matristen çapraz vektör alabilirsiniz; Bir vektörü .asDiagonal() ile çapraz matris olarak ele alabilirsiniz; ama yoğun matrisi çapraz matris olarak ele alamazsınız. Yani bu satır

MatrixXd M = (Q_tr * X.inverse() * q).diagonal(); 
+1

Bu sorun tamamen çözülmüş ve algoritma elipsi bulur. C++ yerine doğrusal cebir anlayışım eksikliğinden kaynaklanıyor gibi görünüyor. Teşekkür ederim! – Dziugas