2013-02-19 4 views
18

Этот вопрос уже был asked, но я до сих пор его не понимаю. Я получаю матрицу гомографии, вызывая cv::findHomography из набора точек. Мне нужно проверить, насколько это актуально или нет.
Предлагаемый метод состоит в том, чтобы вычислить максимальную ошибку повторения для линеек и сравнить ее с порогом. Но после такой фильтрации я продолжаю получать безумные преобразования с объектной ограничивающей коробкой, преобразующейся почти в прямую линию или какой-то странный невыпуклый четырехугольник, с самопересечениями и т. Д.
Какие ограничения могут быть использованы для проверки правильности матрицы гомографии?Как проверить правильность полученной матрицы гомографии?

+0

См [это] [1] ответ я отправил некоторое время назад. [1]: http://stackoverflow.com/questions/10972438/detecting-garbage-homographies-from-findhomography-in-opencv/10981249#10981249 –

ответ

25

Ваш вопрос является математическим. Учитывая, что матрица 3x3 определяет, является ли она хорошей жесткой трансформацией. Трудно определить, что такое «хорошо», но вот некоторые подсказки, которые могут помочь вам

  1. гомографии должны сохранять направление ломаных точек. Проведите простой тест. точки (0,0), (imwidth, 0), (ширина, высота), (0, высота) представляют собой четырехугольник с расположенными по часовой стрелке точками. Примените гомографию к этим точкам и посмотрите, по-прежнему ли они расположены по часовой стрелке, если они вращаются против часовой стрелки. Ваша гомография переворачивает (зеркалирует) изображение, которое иногда по-прежнему в порядке. Но если ваши очки не в порядке, чем у вас есть «плохая гомография»
  2. Гомография не слишком сильно изменяет масштаб объекта. Например, если вы ожидаете, что оно сократится или увеличит изображение с коэффициентом до X, просто проверьте это правило. Преобразуйте 4 точки (0,0), (imwidth, 0), (ширина-1, высота), (0, высота) с помощью гомографии и вычислите площадь четырехугольника (opencv-метод вычисления площади многоугольника), если отношение областей слишком велико (или слишком мало), вероятно, у вас есть ошибка.
  3. Хорошая гомография обычно использует низкие значения перспективы. Обычно, если размер изображения составляет ~ 1000x1000 пикселей, эти значения должны быть ~ 0,005-0,001. Высокая перспектива приведет к огромным искажениям, которые, вероятно, являются ошибкой. Если вы не знаете, где находятся эти значения, прочитайте мой пост: trying to understand the Affine Transform . Он объясняет математику аффинного преобразования, а остальные 2 - перспективные параметры.

Я думаю, что если вы проверите вышеуказанное условие 3 (условие 2 является самым важным), вы сможете обнаружить большинство проблем. Удача

+1

В дополнение к первой проверки предложение HTTP://answers.opencv.org/question/2588/check-if-homography-is-good/. Вычисляя детерминант того, что должно быть подматрицей вращения в гомографии, и проверяя, больше ли он или меньше нуля, указывает вам, была ли сохранена ориентация (в основном вычисление такой детерминанты является эквивалентом формулы Пифагора). – rbaleksandar

0

Редактировать: Этот ответ не имеет отношения к вопросу, но обсуждение может быть полезно для тех, кто пытается использовать соответствующие результаты для распознавания, как я!

Это может помочь кому-то:

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

слишком много кода без комментариев только * полезно * для отчаянных – user3085931

+0

Я думаю, что имена функций объясняют сами. Это то, что я мог бы сделать.Резюме: после преобразования с помощью гомографии он проверяет, является ли найденная форма 1) внутри приемлемой области, 2) размер допустим, 3) форма выпукла или нет (здесь есть ошибка) 4) внутренние углы формы приемлемы или не. Есть несколько ошибок, я обновлю код, когда моя работа закончится. И да, я в отчаянии, если есть другой способ добиться лучшей проверки. Мне также нравится быть отчаянным и читать коды других людей все время. – Koray

+0

FYI: http://stackoverflow.com/questions/11053099/how-can-you-tell-if-a-homography-matrix-is-acceptable-or-not, на мой взгляд, наиболее правдоподобное решение, которое я видел для этой темы. – user3085931