Open
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Перечислите идеи и коротко обозначьте мысли которые у вас возникали по мере выполнения задания, в частности попробуйте ответить на вопросы:
Давайте начнём с конца: сначала выкрутим параметр
ORIENTATION_VOTES_PEAK_RATIO=0.999, а потом будем думать, из-за чего получился тот или иной результат.Но вот блин.. ну выкрутим мы этот параметр, откуда нам знать, что полученный результат зависит только от значения
ORIENTATION_VOTES_PEAK_RATIO, а не от всей нашей реализации SIFT?Поэтому я предлагаю пересобрать OpenCV, заменив значение этого параметра на 0.999.
Прогнав тесты с этим значением (логи), можно увидеть, что ситуация действительно изменилась - причём в лучшую сторону. По угловым тестам (Rotate*, RotateScale и HerzJesu19RotateM40) средняя абсолютная ошибка угла снизилась примерно с 18.66° до 5.77° (уж сорян, но тут я принял волевое решение скормить логи гпт🥺).
Итого, как мы поняли, то, что SIFT менее точно угадывает средний угол отклонения, как-то зависит от тех ситуаций, когда SIFT дублирует ключевую точку с разными пиками ориентациями (а выкрутив
ORIENTATION_VOTES_PEAK_RATIO=0.999мы почти гарантированно избавились от такого дублирования). My guess следующий.. объясню на примере.Имеем ключевую точку на исходной картинке с пиками ориентаций 10° и 40°. После поворота на 90° на получившейся картинке находим согласованную точку, но так получилось, что у неё лишь один пик ориентации: 130°. И вместо того, чтобы сматчить 40° и 130°, мы сматчили одновременно и 10° и 130°, и 40° и 130°, тем самым увеличив среднюю абсолютную ошибку угла отклонения.
Но тут меня посетила чуйка, что как будто бы проблема вообще не в SIFT-е, а в том как мы матчим точки в тестах..
Я провёл ещё один эксперимент: я подредачил код тестов, добавив туда дефайн-флаг
USE_DESCRIPTOR_MATCHING_FOR_ANGLE_DIFF, при включении которого матчинг происходит не по ближайшей точке на искажённом изображении в геометрическом смысле (евклидово расстояние между точками), а берутся все точки, которые проходят геометрический порогerror <= MAX_ACCEPTED_PIXEL_ERROR * width(тут), и уже из них в качестве матча берётся точка, которая наиболее близка "по дескриптору" (по L2-норме для SIFT и по Хэммингу для ORB).Прогнав тесты с включенным
USE_DESCRIPTOR_MATCHING_FOR_ANGLE_DIFF(логи), по угловым тестам средняя абсолютная ошибка угла для SIFT снизилась примерно с 18.66° до 6.22°. Кстати, для ORB она тоже снизилась: c 3.65° до 2.09°.Так что да, то, как мы матчим точки, действительно играет не последнюю роль в том, что SIFT менее точно угадывает средний угол отклонения... но...
Как видно, что с отключенным дублированием точек с разными пиками ориентации, что с изменённой логикой матчинга, ORB всё равно угадывает угол отклонения лучше SIFT. Почему? Полагаю потому, что ORB в принципе заточен на нахождение углов в качестве ключевых точек. А у углов ориентация чаще однозначнее, чем у "пятен", которые в свою очередь может находить SIFT как ключевые точки. А у пятен же может быть почти круглая структура, у которой направление пика ориентации не так очевидно. Отсюда и возникает шум, которые увеличивает среднюю ошибку угла отклонения.
Тут я не понял, что от меня хотят🥴
По заданию в саму реализацию нашего SIFT вроде как не требовалось использовать где-либо OMP.
OMP используется лишь в тестах, причём только в функции
evaluateDetection(), что забавно, ибо в тестах логируется время, потраченное на детекцию.. но OMP используется уже после замера этого времени))Т.е. если подразумевалось, что здесь нужно ответить на вопрос, как надежно замерить, как OMP ускоряет
evaluateDetection(), то придётся писать какой-то свой скрипт для замера.Для надёжности применяются стандартные требования для устойчивых бенчмарков: один и тот же вход; один и тот же набор тестов; warmup прогоны; прогонять несколько раз и брать медиану и/или среднее; стараться во время бенчмарка не иметь в фоне тяжёлых запущенных задач.
Число потоков вроде фиксируется параметром
OMP_NUM_THREADS, в который нужно положить либо1, либоnproc, в зависимости от того, какую версию тестируем на данный момент.Также полезны параметры
OMP_PROC_BIND=trueиOMP_PLACES=cores, которые позволяют закрепить потоки по ядрам, что также повышает надёжность бенчмарка, т.к. устраняются артефакты миграции потоков по ядрам.И если действительно подразумевалось замерить именно OMP в тестах... ну... я замерил... командой
time... никакого ускорения от OMP не заметил от слова совсем👀У меня 6 ядер и 6 потоков, btw🙃
Правда. Эти два способа эквивалентны математически по свойству Гауссиана.
Визуально пирамиды Гауссиана совпадают. Но совпадения пиксель-в-пиксель не гарантируется, ввиду ошибок округления и аппроксимиромации, связанной с тем, что по математике Гауссиан бесконечный (ненулевой везде), а все картинки, очевидно, состоят из конечного числа пикселей, поэтому веса, далёкие от колокола, выкидывают, а оставшиеся - нормируют. Все эти ошибки агрегируются при повторных проходах, из-за чего получается не идентичный результат...
... но я вот чёта нифига никакой визуальной разницы не вижу🙃 (можете сами глянуть тут и тут).
Ну.. ожидаем, что каждый новый слой (в рамках одной октавы, по крайней мере) - это чуть более размытая версия предыдущего слоя :) Причём меняться должна только и только степень размытости. Если вдруг, какой-то слой выглядит резче предыдущего из той же октавы, это баг, и что-то работает некорректно.
Также можно посмотреть на картинки из разных октав, которые должны выглядеть одинаково, ибо каждая следующая октава строится из определённого слоя предыдущей октавы. Конкретно в нашем случае, можно посмотреть на пару картинок octave_{i}_layer_{j} и octave_{i-1}_layer_{j+3}, и они должны выглядеть практически идентично по модулю очень-очень небольшого сдвига, связанного с тем, что функция
savePyramid()делает апскейл, который позволяет нам удобно сравнивать картинки разного размера, а upscale делает линейную интерполяцию, но downscale-им мы, используяdownsample2x, а неdownsample2x_avg, а (слишком много "а", да?)downsample2x, в свою очередь, просто берёт каждый второй пиксель без всякой интерполяции.Ну а ещё я понял, что я уже неявно ответил на последние два вопроса🙃
Мы хотим
sDoG слоёв для поиска экстремумов. Ищем мы экстремумы в 3D, значит, нам нужны ещё два "мнимых" дополнительных слоя сверху и снизу, иначе у верхнего "полезного" слоя не будет "потолка", а у нижнего - не будет "пола". Но DoG слои - это разности слоёв Гауссиана. Если мы хотимs+2разностей, значит нам нужноs+3слоёв, из которых эти разности будут получаться.В первую очередь я бы ожидал хорошо выделенные фичи исходной картинки определённого масштаба. На начальных слоях выражены мелкие фичи: всякие контуры и текстуры, а на глубоких слоях вырисовываются уже различные, более крупные, однородные пятна. Причём на разных слоях один и тот же объект должен быть геометрически согласован, меняться должен только масштаб/характер отклика той или иной части объекта. Т.е. что на верхних, что на глубоких слоях, собачка на картинке не должна никак повернуться, сдвинуться, и т.п., и её очертания, может, с трудом, но должны быть видны даже на достаточно размытом слое.
Потому что чем больше слоёв, тем более похожими будут соседние слои Гауссиана, а значит, DoG будет более однотонным, а значит, экстремумы по своему значению будут меньше, чем экстремумы, которые бы были в этом DoG при меньшем количестве слоёв, а значит без уменьшения порога контрастности, увеличив число слоёв слишком сильно, DoG может оказаться настолько однотонным, что мы выкинем по порогу почти все точки. Поэтому порог и уменьшают обратно пропорционально кол-ву слоёв.
строка 403:
float sigma_win = 1.5f * kp_sigma_octave;строка 606:
float angle_invariant = angle - kp_angle_rad;Github Actions CI