TL; DR: существует ли реализация CANS для RANSAC или других надежных алгоритмов соответствия, которые можно свободно использовать с произвольными двумерными наборами точек?
Я знаю, что существует много реализаций, которые включают в себя или используют алгоритмы соответствия, такие как RANSAC (Random Sampling Consensus). Они часто используются в приложениях компьютерного зрения и находятся в таких библиотеках, как OpenCV, PCL, и т. д. Общий алгоритм хорошо известен и различный сайт списки разные шаги.
Теперь все «продвинутые» реализации (сделанные для OpenCV, PCL и т. Д.), Которые я обнаружил, предназначены для конкретных типов проблем с базовым набором предположений. В OpenCV вы хотите найти матрицу гомографии между первым изображением и частью второго изображения (этот пример). В PCL вы находитесь в сфере трехмерных облаков точек и, насколько мне известно, способны сопоставлять только определенные, уже определенные формы (линия, сфера и т. д.).
То, что я «просто» хочу сделать, — это взять произвольный 2D-набор точек (который может содержать некоторый шум) и найти соответствие в большем наборе 2D-точек (которые также содержат некоторый шум и другие точки). Для этого не требуется никакого специального обучения модели, кроме ввода двух наборов точек. Я сам в процессе реализации в C ++, но:
Я ни в коем случае не опытный программист, и мне нужно, чтобы все это выполнялось достаточно быстро; предыдущая реализация, выполненная мною хорошо известными алгоритмами (обнаружение контуров, размытие по Гауссу и т. д.), оказалась значительно медленнее (> 10x), чем проверенная реализация.
Простое срывание уже существующей реализации с открытым исходным кодом (например, OpenCV) оказалось вне моих текущих возможностей (слишком много зависимостей и шаблон виртуальной реализации и прочее …)
Итак, если кто-нибудь знает о свободно используемой (как BSD) и проверенной реализации C ++, которую я пропустил …
На удивление трудно найти популярную, легковесную, универсальную реализацию RANSAC на C ++. Я только что выпустил свою общую реализацию RANSAC под лицензией MIT.
https://github.com/drsrinathsridhar/GRANSAC
GRANSAC является универсальным, шаблонным, только для заголовков и многопоточным. Пользователь должен реализовать класс, который наследует AbstractModel. Затем можно выполнить оценку RANSAC для любой модели (например, 2D-линии, 3D-плоскости).
Я проверил это только для подгонки 2D линии, но должно работать и для других проблем. Будем рады добавить больше функций (например, автоматически выбирать количество итераций и т. Д.)
Хорошая реализация RANSAC, LMedS, MSAC, MLESAC C ++ для Windows и Linux находится здесь: https://github.com/sunglok/rtl.
RTL: библиотека шаблонов RANSAC Библиотека шаблонов RANSAC (RTL) является
надежный инструмент регрессии с открытым исходным кодом, особенно с семейством RANSAC. РТЛ
стремится обеспечить быстрые, точные и простые способы оценки любой модели
параметры с данными, загрязненными выбросами (неверные данные). РТЛ
включает в себя последние варианты RANSAC с их оценкой производительности с
несколько моделей с синтетическими и реальными данными. RTL написан в общем
стиль программирования (шаблон в C ++) для его дальнейшего применения с
пользовательские модели. RTL распространяется под Упрощенный BSD
Лицензия.
Основной класс RANSAC:
template <class Model, class Datum, class Data>
class RANSAC;
Другие классы наследуются от него:
template <class Model, class Datum, class Data>
class MLESAC : virtual public RANSAC<Model, Datum, Data>
...
Использование простое (пример из README):
// Find the best model using RANSAC
LineEstimator estimator;
RTL::RANSAC<Line, Point, std::vector<Point> > ransac(&estimator);
Line model;
double loss = ransac.FindBest(model, data, data.size(), 2);
// Determine inliers using the best model if necessary
std::vector<int> inliers = ransac.FindInliers(model, data, data.size());
Бумага: https://sites.google.com/site/sunglok/files/Choi09_bmvc.pdf?attredirects=0
Я искал что-то подобное, а потом я нашел этот.
Код находится на с ++ в нижней части.
Функция ниже была первоначально извлечена из этого учебный класс.
cv::Mat ransacTest(const std::vector<cv::DMatch>& matches, const std::vector<cv::KeyPoint>& keypoints1,const std::vector<cv::KeyPoint>& keypoints2, std::vector<cv::DMatch>& outMatches) {
// Convert keypoints into Point2f
std::vector<cv::Point2f> points1, points2;
cv::Mat fundemental;
for (std::vector<cv::DMatch>::const_iterator it= matches.begin(); it!= matches.end(); ++it) {
// Get the position of left keypoints
float x= keypoints1[it->queryIdx].pt.x;
float y= keypoints1[it->queryIdx].pt.y;
points1.push_back(cv::Point2f(x,y));
// Get the position of right keypoints
x= keypoints2[it->trainIdx].pt.x;
y= keypoints2[it->trainIdx].pt.y;
points2.push_back(cv::Point2f(x,y));
}
// Compute F matrix using RANSAC
std::vector<uchar> inliers(points1.size(),0);
if ( points1.size() > 0 && points2.size() > 0 ){
cv::Mat fundemental= cv::findFundamentalMat(
cv::Mat(points1),cv::Mat(points2), // matching points
inliers, // match status (inlier or outlier)
CV_FM_RANSAC, // RANSAC method
3.0, // distance to epipolar line
0.99); // confidence probability
// extract the surviving (inliers) matches
std::vector<uchar>::const_iterator itIn= inliers.begin();
std::vector<cv::DMatch>::const_iterator itM= matches.begin();
// for all matches
for ( ;itIn!= inliers.end(); ++itIn, ++itM) {
if (*itIn) { // it is a valid match
outMatches.push_back(*itM);
}
}
// The F matrix will be recomputed with all accepted matches
// Convert keypoints into Point2f for final F computation
points1.clear();
points2.clear();
for (std::vector<cv::DMatch>::const_iterator it= outMatches.begin(); it!=outMatches.end(); ++it) {
// Get the position of left keypoints
float x= keypoints1[it->queryIdx].pt.x;
float y= keypoints1[it->queryIdx].pt.y;
points1.push_back(cv::Point2f(x,y));
// Get the position of right keypoints
x= keypoints2[it->trainIdx].pt.x;
y= keypoints2[it->trainIdx].pt.y;
points2.push_back(cv::Point2f(x,y));
}
// Compute 8-point F from all accepted matches
if( points1.size() > 0 && points2.size() > 0){
fundemental= cv::findFundamentalMat(
cv::Mat(points1),cv::Mat(points2), // matches
CV_FM_8POINT); // 8-point method
}
}
return fundemental;
}