2015-03-10 3 views
2

J'essaye d'implémenter this answer de math.stackexchange dans eclispe avec C++ et OpenCV 3.0.0 (bêta).
J'utilise le code ci-dessous pour cela.Comment convertir 'cv :: Mat' en 'double'?

Mat a = (Mat_<double>(1,3) << rotationMatrix1.at<double>(2,0), rotationMatrix1.at<double>(2,1), rotationMatrix1.at<double>(2,2)); 
Mat b = (Mat_<double>(1,3) << rotationMatrix2.at<double>(2,0), rotationMatrix2.at<double>(2,1), rotationMatrix2.at<double>(2,2)); 

Mat f = (Mat_<double>(1,3) << a , (b-(a.dot(b))*a)/norm(b-(a.dot(b))*a),a.cross(b)); 
Mat f1 = f.inv(DECOMP_CHOLESKY); 

Mat g = (Mat_<double>(3,3) << a.dot(b), - norm(a.cross(b)), 0, norm(a.cross(b)), a.dot(b), 0, 0,0,1); 

Mat u = f1.inv(DECOMP_CHOLESKY) * g * f1; 

quand je compile cela se traduit par l'erreur suivante:

/include/opencv2/core/mat.inl.hpp:2827:15: error: invalid cast from type 'cv::MatExpr' to type 'double'
/include/opencv2/core/mat.inl.hpp:2827:15: error: invalid cast from type 'cv::Mat' to type 'double'

Le problème réside probablement dans cette ligne:

Mat f = (Mat_<double>(1,3) << a , (b-(a.dot(b))*a)/norm(b-(a.dot(b))*a),a.cross(b)); 

parce que "a" et « (b- (a.dot (b)) * a)/norme (b- (a.dot (b)) * a) "ne sont pas 'doubles'.
Donc, ma question est de savoir comment les convertir en «double» de manière correcte?

Répondre

0

Pour une meilleure lisibilité Réécrivons votre ligne

Mat f = (Mat_<double>(1,3) << a , (b-(a.dot(b))*a)/norm(b-(a.dot(b))*a),a.cross(b));  

à ceci:

cv::Mat t0 = b - a.dot(b) * a; // size: 1x3 
cv::Mat t1 = t0/norm(t0);  // size: 1x3 
cv::Mat t2 = a.cross(b);   // size: 1x3 
Mat f = (Mat_<double>(1,3) << a , t1 , t2); 
//       ^ ^^ ^^ these are 1x3 matrices (== 9 double value), 
//          but matrix f expects 3 doubles. 

En regardant le math stack question que vous faites référence à , la fonction

FFi = @(A,B) [ A (B-dot(A,B)*A)/norm(B-dot(A,B)*A) cross(B,A) ]; 

renvoie une matrice 3 par 3, donc je En aucun cas Mat_<double>(1,3) est faux.

Pour résoudre ce problème créer un 3 par 3 matrice et affecter les valeurs des variables temporaires ci-dessus aux colonnes de cette matrice:

cv::Mat1d f(3,3); 
f(cv::Rect(0, 0, 1, 3)) = a.t(); // transposed, cf. note below 
f(cv::Rect(0, 0, 2, 3)) = t1.t(); // transposed, cf. note below 
f(cv::Rect(0, 0, 3, 3)) = t2.t(); // transposed, cf. note below 

Note: Faites attention à vos vecteurs sont 1 par 3, pas 3 par 1 comme dans la question référencée. Si vous êtes chanceux, cela déclenche des erreurs d'exécution. Si ce n'est pas le cas, votre code se compile et s'exécute, mais vos résultats sont erronés.

+0

Merci, j'avais oublié que f est une matrice 3x3 – sadhi

0

"Convertir" n'est pas la bonne chose à faire. Vous avez une erreur dans votre expression. Une des fonctions d'OpenCV prend un double et vous passez une matrice. Maintenant qu'une ligne contient environ une douzaine d'appels de fonction (avec tous les opérateurs inclus), il est difficile de choisir celui qui est en faute ici.

Il suffit d'écrire les définitions des variables temporaires pour les différentes sous-expressions. Vous trouverez probablement que l'une de ces sous-expressions, qui selon vous est évaluée en double, est évaluée en tant que matrice. Cette expression est en faute. Ne pas "réparer" pour faire disparaître l'erreur. Fixez-le de sorte que le résultat devienne significatif.

E.g. vous avez peut-être oublié de prendre le déterminant d'une matrice quelque part, et nous n'aurions aucune idée - nous ne sommes pas des experts du domaine. Le compilateur C++ n'est pas non plus. Il ne sait rien sur les déterminants, il détecte juste une discordance de type. Et de toute évidence, en prenant le déterminant d'une matrice n'est pas une « conversion »