2013-06-10 2 views
2

Я копал в OpenCV's implementation of SIFT descriptor extraction. Я натолкнулся на какой-то загадочный код, чтобы получить радиус окрестности точки интереса. Ниже приводится аннотированный код с переменной имена изменены, чтобы быть более описательным:Радиус действия ключа 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 строки и последнюю строку.

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

ответ

8

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

Действительно эта реализация SIFT кодирует несколько значений в пределах атрибута KeyPointoctave. Если вы обратитесь к line 439 вы можете увидеть, что:

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

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

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

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

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

Это отображение вычисляется на line 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 вычисляются путем умножения:

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

Действительно, вы можете найти подробное описание в vlfeat's SIFT implementation:

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

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

+0

спасибо! Это отличное описание. – greenbeansugar

+0

Благодарим вас за подробное объяснение! Единственное, чего я еще не понимаю: обычно ключевые точки не должны обнаруживаться в самом верхнем масштабе (помните, что проверка экстремумов с 26 соседями, которые являются пикселями вокруг и соседями в следующих масштабах?) Итак, почему здесь SIFT создал ключевую точку со шкалой 2 (октава -1)? –

Смежные вопросы