У меня есть вопрос о последней части задания 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?
Таким образом, числа из вектора объектов должны быть не больше 0,2
значение.
Нет. В документе говорится, что дескрипторы SIFT:
0.2
в качестве порогового значения (т. е. зацикливание на нормализованных значениях и усечение при необходимости)Таким образом, в теории любой компонент дескриптора 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]
спектр.
Других решений пока нет …