2013-02-19 5 views
18

Cette question était déjà asked, mais je ne comprends toujours pas. J'obtiens une matrice d'homographie en appelant cv::findHomography à partir d'un ensemble de points. Je dois vérifier si c'est pertinent ou non.
La méthode proposée consiste à calculer l'erreur maximale de reprojection pour les inliers et à la comparer avec un seuil. Mais après une telle filtration, je continue d'obtenir des transformations insensées avec une boîte de délimitation d'objet qui se transforme en une ligne droite ou en un quadrilatère étrange non convexe, avec des auto-intersections, etc.
Quelles contraintes peuvent être utilisées pour vérifier si la matrice d'homographie est adéquate?Comment vérifier si la matrice d'homographie obtenue est bonne?

+0

Voir [ce] [1] réponse que je posté il y a quelque temps. [1]: http://stackoverflow.com/questions/10972438/detecting-garbage-homographies-from-findhomography-in-opencv/10981249#10981249 –

Répondre

25

Votre question est mathématique. Étant donné une matrice de 3x3, décidez si elle représente une bonne transformation rigide. Il est difficile de définir ce qui est « bon », mais voici quelques indices qui peuvent vous aider

  1. Homographie devrait conserver la direction de points polygonales. Concevoir un test simple. les points (0,0), (imwidth, 0), (width, height), (0, height) représentent un quadrilatère avec des points disposés dans le sens des aiguilles d'une montre. Appliquez l'homographie sur ces points et voyez s'ils sont toujours disposés dans le sens des aiguilles d'une montre s'ils deviennent dans le sens contraire des aiguilles d'une montre votre homographie est en train de retourner l'image qui est parfois toujours correcte. Mais si vos points sont en panne que vous avez une "mauvaise homographie"
  2. L'homographie ne change pas trop l'échelle de l'objet. Par exemple, si vous vous attendez à ce qu'il rétrécisse ou agrandisse l'image d'un facteur X, il suffit de vérifier cette règle. Transformer les 4 points (0,0), (imwidth, 0), (width-1, height), (0, height) avec l'homographie et calculer l'aire du quadrilatère (méthode opencv de calcul de polygone) si le ratio des zones est trop grande (ou trop petite), vous avez probablement une erreur.
  3. Une bonne homographie utilise généralement de faibles valeurs de perspectivité. Généralement, si la taille de l'image est de ~ 1000x1000 pixels, ces valeurs doivent être de ~ 0.005-0.001. Une grande perspectivité provoquera d'énormes distorsions qui sont probablement une erreur. Si vous ne savez pas où se trouvent ces valeurs, lisez mon article: trying to understand the Affine Transform . Il explique les maths de transformation affine et les deux autres valeurs sont des paramètres de perspective.

Je pense que si vous vérifiez la condition 3 ci-dessus (condition 2 est le plus important), vous serez en mesure de détecter la plupart des problèmes. Bonne chance

+1

En plus de la première vérification de suggestion http://answers.opencv.org/question/2588/check-if-homography-is-good/. Calculer le déterminant de ce qui est censé être une sous-matrice de rotation dans l'homographie et vérifier si elle est plus ou moins nulle vous indique si l'orientation a été préservée (le calcul de ce déterminant est l'équivalent de la formule de Pythagore). – rbaleksandar

0

Éditer: Cette réponse n'est pas pertinente à la question, mais la discussion peut être utile pour quelqu'un qui essaie d'utiliser les résultats correspondants pour la reconnaissance comme je l'ai fait!

Cela pourrait aider quelqu'un:

Point2f[] objCorners = { new Point2f(0, 0), 
    new Point2f(img1.Cols, 0), 
    new Point2f(img1.Cols, img1.Rows), 
    new Point2f(0, img1.Rows) }; 

Point2d[] sceneCorners = MyPerspectiveTransform3(objCorners, homography); 
double marginH = img2.Width * 0.1d; 
double marginV = img2.Height * 0.1d; 
bool homographyOK = isInside(-marginH, -marginV, img2.Width + marginH, img2.Height + marginV, sceneCorners); 
if (homographyOK) 
    for (int i = 1; i < sceneCorners.Length; i++) 
     if (sceneCorners[i - 1].DistanceTo(sceneCorners[i]) < 1) 
     { 
      homographyOK = false; 
      break; 
     } 
if (homographyOK) 
    homographyOK = isConvex(sceneCorners); 
if (homographyOK) 
    homographyOK = minAngleCheck(sceneCorners, 20d); 




    private static bool isInside(dynamic minX, dynamic minY, dynamic maxX, dynamic maxY, dynamic coors) 
     { 
      foreach (var c in coors) 
       if ((c.X < minX) || (c.Y < minY) || (c.X > maxX) || (c.Y > maxY)) 
        return false; 
      return true; 
     }  
     private static bool isLeft(dynamic a, dynamic b, dynamic c) 
     { 
      return ((b.X - a.X) * (c.Y - a.Y) - (b.Y - a.Y) * (c.X - a.X)) > 0; 
     } 
     private static bool isConvex<T>(IEnumerable<T> points) 
     { 
      var lst = points.ToList(); 
      if (lst.Count > 2) 
      { 
       bool left = isLeft(lst[0], lst[1], lst[2]); 
       lst.Add(lst.First()); 
       for (int i = 3; i < lst.Count; i++) 
        if (isLeft(lst[i - 2], lst[i - 1], lst[i]) != left) 
         return false; 
       return true; 
      } 
      else 
       return false; 
     } 
     private static bool minAngleCheck<T>(IEnumerable<T> points, double angle_InDegrees) 
     { 
      //20d * Math.PI/180d 
      var lst = points.ToList(); 
      if (lst.Count > 2) 
      {     
       lst.Add(lst.First()); 
       for (int i = 2; i < lst.Count; i++) 
       { 
        double a1 = angleInDegrees(lst[i - 2], lst[i-1]); 
        double a2 = angleInDegrees(lst[i], lst[i - 1]); 
        double d = Math.Abs(a1 - a2) % 180d; 

        if ((d < angle_InDegrees) || ((180d - d) < angle_InDegrees)) 
         return false; 
       } 
       return true; 
      } 
      else 
       return false; 
     } 
     private static double angleInDegrees(dynamic v1, dynamic v2) 
     { 
      return (radianToDegree(Math.Atan2(v1.Y - v2.Y, v1.X - v2.X))) % 360d; 
     } 
     private static double radianToDegree(double radian) 
     { 
      var degree = radian * (180d/Math.PI); 
      if (degree < 0d) 
       degree = 360d + degree; 

      return degree; 
     } 
     static Point2d[] MyPerspectiveTransform3(Point2f[] yourData, Mat transformationMatrix) 
     { 
      Point2f[] ret = Cv2.PerspectiveTransform(yourData, transformationMatrix); 
      return ret.Select(point2fToPoint2d).ToArray(); 
     } 

enter image description here

+0

trop de code sans commentaire est seulement * utile * pour les désespérés – user3085931

+0

Je pense que les noms de fonctions s'expliquent. C'est celui que je pourrais faire.Résumé: Il vérifie, après transformation par homographie, si la forme trouvée est 1) dans une région acceptable, 2) la taille est acceptable, 3) la forme est convexe ou non (il y a une erreur ici) 4) les angles internes de la forme sont acceptables ou ne pas. Il y a quelques erreurs, je mettrai à jour le code quand mon travail sera terminé. Et oui, je suis désespéré s'il y a un autre moyen de réaliser un meilleur contrôle. J'aime aussi être désespéré et lire les codes des autres peuples tout le temps. – Koray

+0

FYI: http://stackoverflow.com/questions/11053099/how-can-you-tell-if-a-homography-matrix-is-acceptable-or-not est à mon avis la solution la plus plausible que j'ai vue pour ce sujet. – user3085931

Questions connexes