сравнение SIFT дескрипторов особых точек (OpenCV 3)

241
28 ноября 2017, 22:50

Буду очень признателен, если коллеги подскажут ссылку или исходник, где можно подсмотреть, как правильно добираться до значений вектора дескрипторов ключевых (особых) точек изображения, полученных с помощью SIFT детектора. О существовании cv::DescriptorMatcher мне известно, однако в моем случае хотелось бы обойтись менее громоздкими способами. Ниже воспроизводимый проблемный код:

#include "opencv2/xfeatures2d.hpp"
#include "opencv2/imgproc.hpp"
 //Проблемы в этой  функции, скачанной из Интернет
double euclidDistance(cv::Mat& vec1, cv::Mat& vec2) {
double sum = 0.0;
int dim = vec1.cols;
for (int i = 0; i < dim; i++) {
    sum += (vec1.at<uchar>(0, i) - vec2.at<uchar>(0, i)) * (vec1.at<uchar>(0, i) - vec2.at<uchar>(0, i));
}
return sqrt(sum);
}

void _produceAnalogyPoints(cv::Mat img)
{
//Создаем стандартный SIFT детектор
cv::Ptr<cv::Feature2D> f2d = cv::xfeatures2d::SIFT::create();
//Выделяем из входного изображения все особые точки
std::vector<cv::KeyPoint> keypoints;
f2d->detect(img, keypoints);
//Для каждой особой точки строим вектор дескрпторов
cv::Mat descriptors;
f2d->compute(img, keypoints, descriptors);
//Для каждой пары особых точек с близкими дискрипторами и удовлетовояющих некоторому дополнительнуму критерию _geometrySuitable(pt1, pt2) выполняем некую операцию
    for (int i = 0; i < keypoints.size(); i++)
    {
        cv::KeyPoint pt1 = keypoints[i];
        for (int j = i + 1; j < keypoints.size(); j++)
        {
              //Отсеиваем  особые точки, не удовлетворяющие определенному критерию 
              cv::KeyPoint pt2 = keypoints[j];
              //if (_geometrySuitable(pt1, pt2) ) - будем считать, что проверка прошла
              {
               //Расстояние между дескрипторами
               cv::Mat desc1 = descriptors.row(i);
               cv::Mat desc2 = descriptors.row(j);
               //Здесь проблема - как правильно вычислять меру близости дескрипторов ? Подойдет любая мера, желательно нормированная, в том числе и коэффициент корреляции.
               double d = euclidDistance(desc1, desc2);
               if (d < 0.01)
                {
                //Делаем некие полезные действия
                //........................
                }
          }
      }
   }
}

При выполнении этого кода в функции euclidDistance(...) (она скачана из Интернет) возникает исключение "Unhandled exception at 0x000007FEFD52A06D in program.exe: Microsoft C++ exception: cv::Exception at memory location 0x000000000022EBF0."

Это происходит в этом месте:sum += (vec1.at<uchar>(0, i) - vec2.at<uchar>(0, i)) * (vec1.at<uchar>(0, i) - vec2.at<uchar>(0, i)); при вызове функции доступа к элементам вектора vec1.at<uchar>(0, i)

Собственно вопрос - как правильно выдернуть из дескриптора отдельное значение, и нет ли кроме cv::DescriptorMatcher других менее затратных и громоздких способов сравнения двух дескрипторов?

P.S.:Видимо, нужно уточнить проблему - cv::DescriptorMatcher (возможно, я не все про него знаю) дает абсолютную меру, а хотелось иметь оценку близости в виде нормированного коэффициента, вроде коэффициента корреляции d=(XY)/(||X|| ||Y||). Очевидно, что функцию euclidDistance(...), скачанную из Интернет, очень просто оптимизировать и переделать для вычисления коэффициента корреляции, но она валится в Exception при попытке извлечь дескриптор.

READ ALSO
Работа с вектором классов C++

Работа с вектором классов C++

Дано: два вектора классов

221
Как получить адрес kernel32.dll

Как получить адрес kernel32.dll

Как получить адрес kernel32dll не используя функции WinAPI?

218