[Просим вас прочитать детали вопроса, прежде чем пометить его как дубликат или отказаться от голосования. Я тщательно искал и не мог найти решение, и поэтому разместил вопрос здесь.]
Я пытаюсь сравнить одно изображение с несколькими изображениями и получить список всех подходящих изображений. Я не хочу рисовать ключевые точки между изображениями.
Мое решение основано на следующем исходном коде:
https://github.com/Itseez/opencv/blob/master/samples/cpp/matching_to_many_images.cpp
Приведенный выше исходный код соответствует одно изображение с несколькими изображениями и получить наиболее подходящее изображение.
Я изменил приведенный выше пример и сгенерировал:
vector<vector<DMatch>> matches;
vector<vector<DMatch>> good_matches;
Теперь мой вопрос: как применить коэффициент поиска ближайшего соседа, чтобы получить хорошие совпадения для нескольких изображений?
Изменить 1:
Моя реализация выглядит следующим образом:
Для каждого изображения в наборе данных вычисляют дескрипторы SURF.
Объедините все дескрипторы в одну большую матрицу.
Создайте индекс FLANN из объединенной матрицы.
Вычислить дескрипторы для изображения запроса.
Запустите KNN-поиск по индексу FLANN, чтобы найти топ 20 или меньше лучшее соответствие изображения. К установлен как 20.
Отфильтруйте все неадекватные совпадения, вычисленные на предыдущем шаге. (Как??)
Я успешно выполнил шаги с 1 по 5. Я столкнулся с проблемой на шаге 6, когда не могу удалить ложные совпадения.
Есть два ответа на вашу проблему. Во-первых, вы должны использовать совершенно другую технику, второй ответ — как на самом деле делать то, что вы просили.
Вы хотите найти дубликаты данного изображения запроса. Традиционно вы делаете это, сравнивая Глобальный дескрипторы изображений, а не местный дескрипторы функций.
Самый простой способ сделать это — объединить дескрипторы локальных объектов в локальный дескриптор. Стандартный метод здесь — «мешок визуальных слов». В OpenCV это называется Bag-Of-Words (например, BOWTrainer
, BOWImgDescriptorExtractor так далее). Посмотрите на документацию для использования этого.
Есть некоторый пример кода в samples/cpp/bagofwords_classification.cpp
выгоды будет то, что вы получите более надежные результаты (в зависимости от реализации того, что вы делаете сейчас), и что сопоставление обычно происходит быстрее.
Я понимаю, что вы хотите удалить точки из входных данных, которые приводят к ложным срабатываниям при вашем сопоставлении.
Вы не можете удалить очки из FLANN (1, 2, 3). FLANN строит дерево для быстрого поиска. В зависимости от типа дерева удаление узла становится невозможным. Угадайте, что FLANN использует KD-дерево, которое (легко) не позволяет удалять точки.
FlannBasedMatcher не поддерживает маскирование допустимых совпадений наборов дескрипторов, потому что flann :: Index не поддерживает это.
Я бы предложил использовать поиск по радиусу вместо простого поиска. Или посмотрите на L2-расстояние найденных совпадений и напишите в своем коде функцию, чтобы увидеть, падает ли расстояние ниже порогового значения.
Я также должен отметить, что вы можете восстановить свое фланг. Очевидно, что при этом снижается производительность. Но если у вас большое количество запросов и некоторые функции слишком часто становятся ложными срабатываниями, возможно, имеет смысл сделать это один раз.
Вам нужны функции DescriptorMatcher::clear()
а потом DescriptorMatcher::add(const vector<Mat>& descriptors)
за это. Referenz.
Во-первых, вам нужно определить «неадекватные совпадения», без этого определения вы ничего не сможете сделать.
Есть несколько свободных определений, которые приходят на ум:
1: неадекватные совпадения = совпадение с расстоянием> предварительно определенное расстояние
В этом случае поиск по фланговому радиусу может быть более подходящим, поскольку он даст вам только те индексы в пределах предварительно определенного радиуса от цели:
2: неадекватные совпадения = совпадение с расстоянием> динамически определенное расстояние на основе найденного k-nn
Это сложнее, и мне кажется, что у меня есть два возможных решения:
2a: Определить некоторый коэффициент теста на основе расстояния первого 1-NN, например:
базовое расстояние = расстояние до 1NN
неадекватное match_k = match distance_k> = a * базовое расстояние;
2b: Использовать метод динамической пороговой привязки, такой как порог Оцу, для нормализованного распределения расстояний для k-nn, таким образом, разделив k-nn на две группы, группа, которая содержит 1-nn, является адекватной группой, другая это неадекватная группа.
http://en.wikipedia.org/wiki/Otsu«S_method,
http://docs.opencv.org/modules/imgproc/doc/miscellaneous_transformations.html#threshold.