OpenCV (C++) с использованием дескрипторов SIFT увеличивает количество обнаруженных функций?

У меня немного запутанная ситуация при использовании реализации дескрипторов SIFT из OpenCV.

Я пытаюсь протестировать различные методы расчета детектора признаков + дескриптора, поэтому я использую комбинацию интерфейсов cv::FeatureDetector и cv::DescriptorExtractor, которые позволяют мне просто переключаться между различными методами обнаружения и дескрипторами.

При вызове cv::DescriptorExtractor::compute(...) (вариант для одиночного изображения) в документации сказано, что возможно количество ключевых точек, отдаваемых алгоритму, уменьшаться, если невозможно вычислить их дескрипторы, и я так понимаю как и зачем это делается.

Но что происходит со мной, так это то, что количество ключевых точек после вычислений дескриптора фактически увеличивается. Это явно так, и я не пытаюсь предотвратить это, я просто надеюсь на объяснение, почему (просто интуитивное описание было бы круто, хотя я ценю что-то большее).

У меня есть слои за слоями оболочек вокруг фактического OpenCV, которые не имеют никакого кода (просто устанавливаю некоторые локальные флаги, отличные от OpenCV), так что вот код OpenCV, который вызывается внизу всего этого:

cv::Ptr<cv::FeatureDetector> dect = cv::FeatureDetector::create("MSER");
cv::Mat input = cv::imread("someImg.ppm", 0);
std::vector<cv::KeyPoint> keypoints;
dect->detect(input, keypoints);

cv::Ptr<cv::DescriptorExtractor>deEx=cv::DescriptorCalculator::create("SIFT");

std::cout << "before computing, feats size " << keypoints.size() << std::endl;
// code to print out 10 features

cv::Mat desc;
deEx->compute(input, keypoints, desc);

std::cout << "after computing, feats size " << keypoints.size() << std::endl;
// code to print out 10 features

Я распечатал первые 10 ключевых точек непосредственно перед и после вычисления дескриптора, так что вот несколько конкретных цифр в качестве примера:

before computing, feats size 379
feat[0]: 10.7584 39.9262 176.526 0 12.5396
feat[1]: 48.2209 207.904 275.091 0 11.1319
feat[2]: 160.894 313.781 170.278 0 9.63786
feat[3]: 166.061 239.115 158.33 0 19.5027
feat[4]: 150.043 233.088 171.887 0 11.9569
feat[5]: 262.323 322.173 188.103 0 8.65429
feat[6]: 189.501 183.462 177.396 0 12.3069
feat[7]: 218.135 253.027 171.763 0 123.069
feat[8]: 234.508 353.236 173.281 0 11.8375
feat[9]: 234.404 394.079 176.23 0 8.99652
after computing, feats size 463
feat[0]: 10.7584 39.9262 13.1313 0 12.5396
feat[1]: 48.2209 207.904 69.0472 0 11.1319
feat[2]: 48.2209 207.904 107.438 0 11.1319
feat[3]: 160.894 313.781 9.57937 0 9.63786
feat[4]: 166.061 239.115 166.144 0 19.5027
feat[5]: 150.043 233.088 78.8696 0 11.9569
feat[6]: 262.323 322.173 167.259 0 8.65429
feat[7]: 189.501 183.462 -1.49394 0 12.3069
feat[8]: 218.135 253.027 -117.067 3 123.069
feat[9]: 218.135 253.027 7.44055 3 123.069

Из этого примера я вижу, что исходные feat[1] и feat[7] расширились до двух новых ключевых точек каждая, но я не вижу никакого логического объяснения тому, как метод compute делает это :(

Распечатка, которую я привел здесь, получена при использовании MSER для обнаружения ключевых точек, а затем при попытке вычислить дескрипторы SIFT, но такое же увеличение в размере также происходит с обнаруженными ключевыми точками STAR, SURF и SIFT (т.е. DoG). Я не пытался изменить дескриптор SIFT на что-то другое, но если кто-то считает, что это имеет отношение к вопросу, я попробую и отредактирую его в своем вопросе.


person penelope    schedule 21.03.2012    source источник
comment
Можете ли вы добавить часть кода, который вы используете? Будет полезно знать параметры.   -  person Alex    schedule 21.03.2012
comment
Эээ... На самом деле я делаю обертки вокруг оберток для кода OpenCV, но я попытаюсь выкопать фактические 5 строк кода, которые выполняют всю работу под всем этим, и отредактировать их.   -  person penelope    schedule 21.03.2012


Ответы (3)


Прежде всего, как видно из документации, cv::DescriptorExtractor::compute возьмите std::vector<cv::Keypoints> в аргументе, который в non const. Это означает, что этот вектор можно модифицировать с помощью cv::DescriptorExtractor::compute. На практике KeyPointsFilter::runByImageBorder и KeyPointsFilter::runByKeypointSize (две функции non-const) применяются к вектору и удаляют ключевую точку, для которой нельзя вычислить дескриптор. Повторное извлечение ключевых точек производиться не будет. Вы должны опубликовать несколько строк кода, которые вы используете для дальнейшей диагностики.

--

Что ж, я, наконец, нашел, где возникает проблема: метод cv::SiftDescriptorExtractor::compute вызывает SIFT::operator(), который (пере)вычисляет ориентацию объектов, а также дублирует точки с несколькими доминирующими ориентациями. Решением может быть изменение descriptorParams.recalculateAngles на false.

person Eric    schedule 21.03.2012
comment
Я знаю, почему функции ::compute разрешено изменять std::vector<cv::Keypoints> и что означает non const. Причина, по которой они указывают в документации, это (и я цитирую) ключевые точки. Ключевые точки, для которых невозможно вычислить дескриптор, удаляются. А с удалением все в порядке. Но когда мои ключевые точки завершают процесс, их становится больше, а не меньше, вот чего я не могу понять. Я также опубликовал реальный код, чтобы лучше понять, о чем распечатка. - person penelope; 21.03.2012
comment
Я хотел быть ясным об этом, чтобы полностью понять вашу проблему. Без кода трудно диагностировать. Я попробовал код, который вы отредактировали, и у меня есть переход на другой тип DesciptorExtractor. Кажется, проблема возникает только с дескриптором Sift. - person Eric; 21.03.2012
comment
Да, я сам дал ответ со ссылками на старую и новую документацию, а также страницу, на которой сообщалось о проблеме. Сначала я не публиковал код, потому что меня больше интересовало, почему это происходит (какой смысл в том, что извлечение дескрипторов SIFT увеличивает количество ключевых точек), чем то, где в коде точно ли это происходило. - person penelope; 22.03.2012

Похоже, это связано с тем, что OpenCV использует реализацию SIFT Роба Хесса, которая иногда дублирует ключевые точки с более чем одной доминирующей ориентацией.

Поиск ошибок, о которых сообщил OpenCV, помог, о проблеме сообщалось здесь.

Это не ошибка, поведение не было исправлено в более новых версиях, а просто задокументировано. Поскольку я обязан версии OpenCV, которую использую сейчас (v2.1), мне не пришло в голову взглянуть на более новая документация для дополнительной информации о поведении, описанном в старый имел для меня смысл.

person penelope    schedule 21.03.2012

Это не ошибка, а дизайн:

SIFT возвращает несколько точек интереса в одном и том же месте с разными ориентациями, если явно не существует единственной доминирующей ориентации. Обычно оценивается до трех (в зависимости от фактического фрагмента изображения) ориентаций.

person Stefan    schedule 02.03.2013