Как SiftDescriptorExtractor из OpenCV преобразует значения дескриптора?

У меня есть вопрос о последней части задания SiftDescriptorExtractor,

Я делаю следующее:

    SiftDescriptorExtractor extractor;
Mat descriptors_object;
extractor.compute( img_object, keypoints_object, descriptors_object );

Теперь я хочу проверить элементы объекта Mat descriptors_object:

std::cout<< descriptors_object.row(1) << std::endl;

вывод выглядит так:

[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 0, 0, 0, 0, 0, 0, 32, 15, 0, 0, 0, 0, 0, 0, 73, 33, 11, 0, 0, 0, 0, 0, 0, 5, 114, 1, 0, 0, 0, 0, 51, 154, 20, 0, 0, 0, 0, 0, 154, 154, 1, 2, 1, 0, 0, 0, 154, 148, 18, 1, 0, 0, 0, 0, 0, 2, 154, 61, 0, 0, 0, 0, 5, 60, 154, 30, 0, 0, 0, 0, 34, 70, 6, 15, 3, 2, 1, 0, 14, 16, 2, 0, 0, 0, 0, 0, 0, 0, 154, 84, 0, 0, 0, 0, 0, 0, 154, 64, 0, 0, 0, 0, 0, 0, 6, 6, 1, 0, 1, 0, 0, 0]

Но в Лоу бумага заявлено, что:

Поэтому мы уменьшаем влияние
большие градиентные величины
пороговые значения в блоке
вектор признаков для каждого не должен быть больше
чем 0,2, а затем перенормировать в
единичная длина. Это означает, что соответствие
величины для больших градиентов
не так важно, и что
распределение ориентаций имеет
больший акцент. Значение 0,2 было
определяется экспериментально с использованием изображений
содержащие различное освещение для
одни и те же 3D объекты.

Таким образом, числа из вектора объектов должны быть не более 0,2 значения.

Вопрос в том, как эти значения были преобразованы в объекте Mat?

4

Решение

Таким образом, числа из вектора объектов должны быть не больше 0,2
значение.

Нет. В документе говорится, что дескрипторы SIFT:

  1. нормализованный (с нормой L2)
  2. усеченный с помощью 0.2 в качестве порогового значения (т. е. зацикливание на нормализованных значениях и усечение при необходимости)
  3. снова нормализовался

Таким образом, в теории любой компонент дескриптора SIFT находится между [0, 1]хотя на практике наблюдаемый эффективный диапазон меньше (см. ниже).

Вопрос в том, как эти значения были преобразованы в объекте Mat?

Они конвертируются из значений с плавающей точкой в unsigned char-s.

Вот соответствующий раздел из OpenCV modules/nonfree/src/sift.cpp calcSIFTDescriptor метод:

float nrm2 = 0;
len = d*d*n;
for( k = 0; k < len; k++ )
nrm2 += dst[k]*dst[k];
float thr = std::sqrt(nrm2)*SIFT_DESCR_MAG_THR;
for( i = 0, nrm2 = 0; i < k; i++ )
{
float val = std::min(dst[i], thr);
dst[i] = val;
nrm2 += val*val;
}
nrm2 = SIFT_INT_DESCR_FCTR/std::max(std::sqrt(nrm2), FLT_EPSILON);
for( k = 0; k < len; k++ )
{
dst[k] = saturate_cast<uchar>(dst[k]*nrm2);
}

С:

static const float SIFT_INT_DESCR_FCTR = 512.f;

Это связано с тем, что классические реализации SIFT позволяют квантовать нормализованные значения с плавающей запятой в unsigned char целое число через множитель 512, который эквивалентен тому, что любой компонент SIFT изменяется между [0, 1/2]и, таким образом, избегать потери точности, пытаясь закодировать полное [0, 1] спектр.

7

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

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

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