2017-03-24 5 views
1

J'ai une tâche assez simple: obtenir des angles d'Euler d'un triangle planaire. Motif ressemble thissolvePNP pour triangle planaire

Ainsi, l'algorithme:

1) obtenir une image de webcam - fait

2) convertir gryascale, filtre, etc. - fait

3) obtenir centres de masse de tous les composants connectés, et les filtrer - fait. Ce qui ressemble à this. Les cercles rouges décrivent les centres de masse des sommets des triangles.

code

est assez simple, mais la voici:

QMap<int, QVector<double> > massCenters(const cv::Mat& image) 
{ 
    cv::Mat output(IMAGE_WIDTH, IMAGE_HEIGHT, CV_32S); 
    cv::connectedComponents(image, output, 8); 

    QMap<int, QVector<double> > result; 

    for (int y = 0; y < IMAGE_HEIGHT; ++y) 
    { 
     for (int x = 0; x < IMAGE_WIDTH; ++x) 
     { 
      int label = output.at<int>(y, x); 

      if (label) 
      { 
       QVector<double> vec = result.value(label, QVector<double>()); 

       if (vec.isEmpty()) 
       { 
        vec.resize(3); 
        vec.fill(0); 
       } 

       vec[0] += x; 
       vec[1] += y; 
       vec[2] += 1; 
       result[label] = vec; 
      } 
     } 
    } 

    return result; 
} 

4) j'appelle solvePNP pour obtenir la rotation & vecteurs de traduction

cv::solvePnP(m_origin, m_imagePoints, m_cameraMatrix, m_distMatrix, m_rvec, m_tvec); 

//this code is for drawing rvec & tvec on a screen 
std::vector<cv::Point3f> axis; 
vector<cv::Point2f> axis2D; 

axis.push_back(Point3f(0.0f, 0.0f, 0.0f)); 
axis.push_back(Point3f(30.0f, 0.0f, 0.0f)); 
axis.push_back(Point3f(0.0f, 30.0f, 0.0f)); 
axis.push_back(Point3f(0.0f, 0.0f, 30.0f)); 

cv::projectPoints(axis, m_rvec, m_tvec, m_cameraMatrix, m_distMatrix, axis2D); 

cv::line(m_orig, axis2D[0], axis2D[1], cv::Scalar(255, 0, 0), 2); 
cv::line(m_orig, axis2D[0], axis2D[2], cv::Scalar(0, 255, 0), 2); 
cv::line(m_orig, axis2D[0], axis2D[3], cv::Scalar(0, 0, 255), 2); 

m_origin est déclarée comme std::vector<cv::Point3f> m_origin; et rempli valeurs (mesurées en mm)

m_origin.push_back(cv::Point3f(0.0f, 51.0f, 0.0f)); 
m_origin.push_back(cv::Point3f(-56.0f, -26.0f, 0.0f)); 
m_origin.push_back(cv::Point3f(56.0f, -26.0f, 0.0f)); 

m_imagePoints est déclaré std::vector<cv::Point2f> m_imagePoints; et contient les coordonnées en pixels des centres de masse (cercles rouges sur le deuxième écran).

Et j'obtenir des résultats assez étranges: this-that

Qu'ai-je essayé et ça ne m'a pas aidé:

1) utilisé double et flotter dans les types m_cameraMatrix, m_distMatrix, m_rvec, m_tvec

2) réarrangés points dans m_origin

3) joué avec solvePnPRansac et ses paramètres d'entrée

4) joué avec les méthodes PnP: itérative et epnp

5) useExtrinsicGuess = true - il aide, mais parfois la solution est "bloquée" et donne des valeurs complètement faux (mille degrés dans le vecteur de rotation)

Et J'ai plusieurs questions:

1) est-ce que l'ordre d'origine et les points d'image sont importants? Comme mentionné here, parfois c'est le cas, mais c'était il y a un an.

2) est-ce que ma tâche peut être résolue d'une autre manière que d'utiliser solvePnP?

Merci. J'apprécierais toute aide!

Répondre

2

solvePnPRansac n'est pas approprié dans votre cas car vous n'avez pas à traiter de données aberrantes.

Je pense que la question que vous observez vient du motif que vous choisissez:

  • il est 3 points
  • et vous ajoutez le barycentre du triangle

Mais à mon avis il est plus ou moins similaire à l'utilisation de seulement 3 points puisque le 4ème point que vous ajoutez est le barycentre du triangle et ne devrait pas donner d'informations supplémentaires dans le problème d'estimation de pose. En ce qui concerne le problème d'estimation de pose à partir de 3 points (P3P), il y a jusqu'à quatre solutions possibles et l'ambiguïté peut être supprimée en utilisant un 4ème point. Quelques références à ce sujet:

Ma recommandation est d'utiliser une forme carrée de 4 points au lieu et un test pour voir si vous observez la même problème (drapeau P3P devrait être bien). Si oui, il y a un problème dans le code ou dans l'étalonnage.

Ici un article que je crois est plus ou moins lié à la question: Why is the Danger Cylinder Dangerous in the P3P Problem?. La figure au cas où le lien devient indisponible:

Danger cylinder

+0

Merci pour votre réponse. En fait, oui, vous aviez raison, parce que mon problème a été résolu, quand j'ai ajouté un point de plus. Un indice de plus: avec CV_P3P j'ai des contours étranges dans la première chaîne de vecteur de rotation, tous les autres angles semblaient bons. Résolu avec CV_EPNP. – vmkan