Theres — пример MATLAB, который сопоставляет два изображения и выдает вращение и масштаб:
https://de.mathworks.com/help/vision/examples/find-image-rotation-and-scale-using-automated-feature-matching.html?requestedDomain=www.mathworks.com
Моя цель — воссоздать этот пример с использованием C ++. Я использую тот же метод обнаружения ключевых точек (Harris), и ключевые точки, кажется, в основном идентичны тем, которые находит Matlab. Все идет нормально.
cv::goodFeaturesToTrack(image_grayscale, corners, number_of_keypoints, 0.01, 5, mask, 3, true, 0.04);
for (int i = 0; i < corners.size(); i++) {
keypoints.push_back(cv::KeyPoint(corners[i], 5));
}
BRISK используется для извлечения функций из ключевых точек.
int Threshl = 120;
int Octaves = 8;
float PatternScales = 1.0f;
cv::Ptr<cv::Feature2D> extractor = cv::BRISK::create(Threshl, Octaves, PatternScales);
extractor->compute(image, mykeypoints, descriptors);
Эти дескрипторы затем сопоставляются с использованием подставки по флангам.
cv::FlannBasedMatcher matcher;
matcher.match(descriptors32A, descriptors32B, matches);
Теперь проблема в том, что около 80% моих матчей неверны и непригодны. Для идентичного набора изображений Matlab возвращает только пару совпадений, из которых только ~ 20% являются ошибочными. Я пытался сортировать совпадения в C ++ по значению расстояния, но безуспешно. Значения находятся в диапазоне от 300 до 700, и даже совпадения с самым низким расстоянием почти полностью неверны.
Теперь для расчета смещения достаточно 20% хороших совпадений, но при проверке неправильных совпадений расходуется много вычислительной мощности. Что может быть лучше для сортировки правильных совпадений или есть что-то очевидное, что я делаю неправильно?
РЕДАКТИРОВАТЬ:
Я переключился с Harris / BRISK на AKAZE, который, кажется, предоставляет гораздо лучшие функции и совпадения, которые можно легко отсортировать по значению расстояния. Единственным недостатком является гораздо более высокое время вычислений. С двумя изображениями шириной 1000 пикселей AKAZE требуется полминуты, чтобы найти ключевые точки (на ПК). Я уменьшил это, уменьшив изображения, что составляет приемлемые ~ 3-5 секунд.
Метод, который вы используете, находит для каждой точки ближайшего соседа, независимо от того, насколько он близок. Две стратегии являются общими:
1. Подберите набор A, чтобы установить B, и установите B в A и оставьте только те совпадения, которые существуют в обоих совпадениях.
2. Используйте 2 knnMatch и выполните проверку соотношения, то есть сохраняйте только совпадения, где 1 NN намного ближе, чем 2 NN, например,
d1 < 0,8 * д2.
Код MATLAB использует SURF. OpenCV также предоставляет SURF, SIFT и AKAZE, попробуйте один из них. Особенно SURF было бы интересно для сравнения.
Других решений пока нет …