Как проверить, хороша ли полученная матрица гомографии?

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


person lizarisk    schedule 19.02.2013    source источник
comment
См. [этот] [1] ответ, который я опубликовал некоторое время назад. [1]. > stackoverflow.com/questions/10972438/   -  person Francesco Callari    schedule 19.02.2013


Ответы (2)


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

  1. Гомография должна сохранять направление многоугольных точек. Разработайте простой тест. точки (0,0), (imwidth,0), (width,height), (0,height) представляют собой четырехугольник с точками, расположенными по часовой стрелке. Примените гомографию к этим точкам и посмотрите, расположены ли они по-прежнему по часовой стрелке, если они становятся против часовой стрелки, ваша гомография переворачивает (зеркально отражает) изображение, которое иногда все еще в порядке. Но если ваши точки не в порядке, значит, у вас «плохая гомография».
  2. Гомография не слишком сильно меняет масштаб объекта. Например, если вы ожидаете, что изображение уменьшится или увеличится в X раз, просто проверьте это правило. Преобразуйте 4 точки (0,0), (imwidth,0), (width-1,height), (0,height) с помощью гомографии и вычислите площадь четырехугольника (метод opencv для вычисления площади многоугольника), если соотношение области слишком велики (или слишком малы), возможно, у вас ошибка.
  3. Хорошая гомография обычно использует низкие значения перспективы. Как правило, если размер изображения составляет ~ 1000x1000 пикселей, эти значения должны быть ~ 0,005–0,001. Высокая перспектива вызовет огромные искажения, которые, вероятно, являются ошибкой. Если вы не знаете, где находятся эти значения, прочитайте мой пост: пытаясь понять Аффинное преобразование . Это объясняет математику аффинного преобразования, а два других значения являются перспективными параметрами.

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

person DanielHsH    schedule 19.02.2013
comment
В дополнение к первому предложению проверьте answers.opencv.org/ вопрос/2588/проверить, хороша ли гомография. Вычисление определителя подматрицы вращения в гомографии и проверка того, больше или меньше нуля, говорит вам, была ли сохранена ориентация (по сути, вычисление такого определителя эквивалентно формуле Пифагора). - person rbaleksandar; 27.05.2014

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

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

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();
        }  

введите здесь описание изображения

person Koray    schedule 24.01.2017
comment
слишком много кода без комментариев полезно только для отчаявшихся - person user3085931; 25.01.2017
comment
Я думаю, что названия функций объясняют сами себя. Это то, что я мог бы сделать. Резюме: Он проверяет, после преобразования с помощью гомографии, находится ли найденная форма 1) внутри допустимой области, 2) допустим размер, 3) форма выпуклая или нет (здесь ошибка) 4) внутренние углы формы допустимы или нет. Есть несколько ошибок, я обновлю код, когда моя работа над этим закончится. И да, я в отчаянии, если есть какой-то другой способ добиться лучшей проверки. Мне также нравится быть отчаянным и постоянно читать коды других людей. - person Koray; 25.01.2017
comment
К вашему сведению: stackoverflow.com/questions/11053099/, на мой взгляд, является наиболее правдоподобным решением, которое я видел для этой темы. - person user3085931; 25.01.2017
comment
Спасибо за эту ссылку. Я читал это раньше. Я думаю, что это слишком зависит от местоположения. Я не понимаю, как это может быть успешным в таком случае: emgu.com/ wiki/images/StopSignDetectionExample1.png - person Koray; 25.01.2017
comment
Если я правильно понял, у вас есть два массива расстояний, объединяющих произвольное количество доступных точек — один с расстояниями друг от друга до и один после преобразования перспективы. Эти расстояния (не местоположения) остаются прежними, если это было правильное определение. Другими словами, имея идеальную гомографию, вы получаете ровно 0 как разницу обоих массивов, в том числе в реальных случаях вам нужно указать диапазон допуска (он определен как ‹ 1 допустим). Для того, что я видел на вашей картинке, это должно поймать ваш случай - person user3085931; 25.01.2017
comment
Я может не правильно понял. Но с изображением, которое я добавил к своему ответу, я думаю, расстояние будет больше 1. Так что этот результат будет отклонен, не так ли? Я ценю, если вы можете объяснить, как я ошибаюсь в этом; если я. - person Koray; 25.01.2017
comment
Пожалуйста, извините, я работаю над этим вопросом только неполный рабочий день. Вы были правы, прямое сравнение расстояний между двумя точками до/после гомографии действительно применимо только для небольшого значения перекоса. Однако что не должно быть затронуто, так это соотношение между двумя расстояниями: d1_before_homography / d2_before_homography != d1_after_homography / d2_after_homography +/- tolerance согласен? - person user3085931; 30.01.2017
comment
Я ценю ваш ответ. Я могу не понять что-то, что вы видите. Знак остановки слева (до гомографии) имеет квадратную форму, скажем, имеет длину 1-1-1-1 на каждом сегменте. Зеленые линии справа — это значения после преобразования, которые выглядят как 2-2-1-1. Примените формулу 1/2==1/2==1/1==1/1 , это нормально для этого для допуска 1. Это та же формула на stackoverflow.com/a/12087175/1266873 Кроме того, в соответствии с этой формулой расстояния могут быть в порядке, но результирующая форма может быть вогнутой или самопересекающейся, что следует отклонить. надеюсь не ошибся и смог ясно выразиться - person Koray; 30.01.2017
comment
Да, я думаю, что у нас другой взгляд на проблему: dx_ before_ гомография относится к вашему левому планарному (то есть идеальному сравнению) изображению знака остановки. dx_ after _ гомография здесь вообще не показана. Это уже искаженное изображение, похожее на плоское (например: inst.eecs.berkeley.edu/~cs194-26/fa15/upload/files/proj7B/ исправленное и обрезанное). Если вы сравните расстояния здесь с расстоянием на исходном изображении, вы можете легко проверить, зашкалила ли ваша гомография или это правдоподобный результат. - person user3085931; 30.01.2017
comment
Я построил матрицу inverseHomogrphy и нашел выпрямленные значения для sceneCorners. Эти значения и расстояния почти одинаковы (-+ ‹0,01) с угловыми точками исходного изображения почти на всех изображениях, которые я пробовал. Однако большинство из них ошибочны и должны быть отвергнуты. Я правда пытаюсь понять, но не могу :( - person Koray; 31.01.2017
comment
Простите меня за отсутствие хорошего объяснения через комментарии. Проще говоря: (1) вы выяснили ключевые моменты. (2) рассчитывается гомография (3) генерируется выпрямленное деформированное изображение (4) используется рассчитанная гомография не только для растяжения изображения, но выяснить, где ключевые точки из (1) находятся на изображении (3). Это просто kp_bef * homography = kp_aftне уверен в порядке матриц и обратной гомографии здесь). (5) Сравните эти КП и проверьте, совпадают ли расстояния в (1) с расстояниями в (4) - не смешивайте (1,4) КП для расчета расстояния - person user3085931; 31.01.2017
comment
Примечание для (5): Вы должны использовать КП из эталонного/идеального изображения для расчета расстояний. kp_bef относится к kp в реальной необработанной сцене, так как, конечно, kp_aft — это растянутые позиции, взятые из реального изображения. т.е. сравните расстояние идеального kp с kp из реальной, но растянутой сцены - person user3085931; 31.01.2017
comment
Извините за поздний ответ, я спросил об этом своих друзей. Я думаю, что я совершенно неправильно понял этот вопрос. Я пытался сделать следующее: использовать матрицу гомографии, чтобы решить, было ли изображение шаблона успешно найдено на тестовом изображении. У меня нет никакой реальной точки зрения или какой-либо другой информации о тестовом изображении. Поэтому я думаю, что мой ответ здесь не имеет отношения к заданному вопросу, а также не является правильным подходом к классификации. Большое спасибо за ваше время и усилия. - person Koray; 07.02.2017
comment
если у меня нет реальной точки зрения или какой-либо другой информации о тестовом изображении означает, что вы не знаете, какой знак следует ожидать, тогда да, действительно, вам нужно, например, перейти к машинному обучению. В противном случае этот подход все еще действителен (хотя сравнение углов между точками до и после может еще больше повысить надежность;) - person user3085931; 08.02.2017
comment
Да, я пытался использовать результаты сопоставления, чтобы предсказать, какой знак присутствует на изображении. - person Koray; 08.02.2017
comment
Если у вас есть не более n признаков для различения (с никаких вариаций, таких как грязь, снег и т. д., как в примере с СТОП выше), то вы вполне можете установить алгоритм с сопоставлением ключевых точек. Однако я не могу сказать, будет ли точность или время обработки лучше, если вместо этого будет использоваться ML. - person user3085931; 08.02.2017
comment
Мои целевые изображения - это снимки с просмотра улиц, поэтому может быть много вариантов. Я мог бы определить места знаков (используя сопоставление на основе формы и цвета, в основном зависит от cv.MatchShapes), однако я изо всех сил пытаюсь предсказать, какой это знак. Интересно, возможно ли это с отдельными шаблонами каждого знака, я пока не нашел. Я попробую методы SVM и подготовлю некоторые обучающие данные. Я бы хотел поговорить с тобой лицом к лицу. - person Koray; 08.02.2017
comment
Я не очень знаком со свойствами SVM в таких областях, в основном я читал о нейронных сетях в этом контексте. Если вы все еще не уверены в том, что подходит лучше всего, чтобы получить лучшее представление, взгляните на документы по распознаванию лиц, так как это почти та же ситуация, но еще более сложная (то есть то, что там работает, должно быть решением для вас!) . Кстати, я думаю, вы должны были открыть новую тему;) - person user3085931; 10.02.2017