Буду очень признателен, если коллеги подскажут ссылку или исходник, где можно подсмотреть, как правильно добираться до значений вектора дескрипторов ключевых (особых) точек изображения, полученных с помощью 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 при попытке извлечь дескриптор.
Современные инструменты для криптотрейдинга: как технологии помогают принимать решения
Апостиль в Лос-Анджелесе без лишних нервов и бумажной волокиты
Основные этапы разработки сайта для стоматологической клиники
Продвижение своими сайтами как стратегия роста и независимости