Радиус ключевой точки дескриптора OpenCV SIFT

Я копался в Реализация OpenCV извлечения дескриптора SIFT. Я натолкнулся на некоторый загадочный код, чтобы получить радиус окрестности точки интереса. Ниже приведен аннотированный код с именами переменных, измененными для большей наглядности:

// keep octave below 256 (255 is 1111 1111)
int octave = kpt.octave & 255;
// if octave is >= 128, ...????
octave = octave < 128 ? octave : (-128 | octave);
// 1/2^absval(octave)
float scale = octave >= 0 ? 1.0f/(1 << octave) : (float)(1 << -octave);
// multiply the point's radius by the calculated scale
float scl = kpt.size * 0.5f * scale;
// the constant sclFactor is 3 and has the following comment:
// determines the size of a single descriptor orientation histogram
float histWidth = sclFactor * scl;
// descWidth is the number of histograms on one side of the descriptor
// the long float is sqrt(2)
int radius = (int)(histWidth * 1.4142135623730951f * (descWidth + 1) * 0.5f);

Я понимаю, что это как-то связано с преобразованием в шкалу, из которой был взят интересующий пункт (я читал статью Лоу), но я не могу связать точки с кодом. В частности, я не понимаю первые 3 строки и последнюю строку.

Мне нужно понять это, чтобы создать аналогичный локальный дескриптор точки для движения.

2

Решение

Я не понимаю первые 3 строки

Действительно это реализация SIFT кодирует несколько значений в пределах KeyPoint octave приписывать. Если вы ссылаетесь на линия 439 ты это видишь:

kpt.octave = octv + (layer << 8) + (cvRound((xi + 0.5)*255) << 16);

Это означает, что октава хранится в первом байтовом блоке, слой во втором байтовом блоке и т. Д.

Так kpt.octave & 255 (который можно найти в unpackOctave method) просто маскирует октаву ключевой точки, чтобы получить эффективное значение октавы.

Также: эта реализация SIFT использует отрицательную первую октаву (int firstOctave = -1) работать с изображением с более высоким разрешением. Поскольку октавные индексы начинаются с 0, вычисляется отображение:

octave index = 0 => 255
octave index = 1 => 0
octave index = 2 => 1
...

Это отображение вычисляется в линия 790:

kpt.octave = (kpt.octave & ~255) | ((kpt.octave + firstOctave) & 255);

Таким образом, вторая строка выше — это просто способ отобразить эти значения:

octave = 255 => -1
octave = 0   => 0
octave = 1   => 1
..

А третья строка — это просто способ вычисления шкалы, учитывая, что отрицательные октавы дают шкалу> 1, например 1 << -octave дает 2 для octave = -1 что означает, что это удваивает размер.

[Я не понимаю] последняя строка.

В основном это соответствует радиусу круга, который обернет квадратное пятно измерения D, следовательно sqrt(2) и деление на 2. D вычисляется умножением:

  • шкала ключевых точек,
  • коэффициент увеличения = 3,
  • ширина гистограммы дескриптора = 4, округленная до следующего целого числа (отсюда +1)

Действительно, вы можете найти подробное описание в реализация SIFT в vlfeat:

Поддержка каждого пространственного бина имеет расширение SBP = 3 сигма
пикселей, где сигма — масштаб ключевой точки. Таким образом, все
Бункеры вместе имеют поддержку SBP x NBP пикселей шириной. поскольку
используется взвешивание и интерполяция пикселя, расширяется поддержка
другой половиной Таким образом, поддержка представляет собой квадратное окно
SBP x (NBP + 1) пикселей. Наконец, так как патч может быть
произвольно повернут, нам нужно рассмотреть окно 2W + = sqrt (2) x
SBP x (NBP + 1) пикселей в ширину.

Наконец, я настоятельно рекомендую вам обратиться к этому vlfeat SIFT документация.

8

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]