2016-03-16 9 views
0

Я использую SIFT для обнаружения, описания точек функции на двух изображениях следующим образом.Почему RANSAC не удаляет все отклонения в матчах SIFT?

void FeaturePointMatching::SIFTFeatureMatchers(cv::Mat imgs[2], std::vector<cv::Point2f> fp[2]) 
{ 
    cv::SiftFeatureDetector dec; 
    std::vector<cv::KeyPoint>kp1, kp2; 

    dec.detect(imgs[0], kp1); 
    dec.detect(imgs[1], kp2); 

    cv::SiftDescriptorExtractor ext; 
    cv::Mat desp1, desp2; 

    ext.compute(imgs[0], kp1, desp1); 
    ext.compute(imgs[1], kp2, desp2); 

    cv::BruteForceMatcher<cv::L2<float> > matcher; 
    std::vector<cv::DMatch> matches; 
    matcher.match(desp1, desp2, matches); 

    std::vector<cv::DMatch>::iterator iter; 

    fp[0].clear(); 
    fp[1].clear(); 
    for (iter = matches.begin(); iter != matches.end(); ++iter) 
    { 
     //if (iter->distance > 1000) 
     // continue; 
     fp[0].push_back(kp1.at(iter->queryIdx).pt); 
     fp[1].push_back(kp2.at(iter->trainIdx).pt); 
    } 

    // remove outliers 
    std::vector<uchar> mask; 
    cv::findFundamentalMat(fp[0], fp[1], cv::FM_RANSAC, 3, 1, mask); 

    std::vector<cv::Point2f> fp_refined[2]; 
    for (size_t i = 0; i < mask.size(); ++i) 
    { 
     if (mask[i] != 0) 
     { 
      fp_refined[0].push_back(fp[0][i]); 
      fp_refined[1].push_back(fp[1][i]); 
     } 
    } 

    std::swap(fp_refined[0], fp[0]); 
    std::swap(fp_refined[1], fp[1]); 
} 

В приведенном выше коде, я использую findFundamentalMat() для удаления выбросов, но в результате img1 и img2 Есть еще некоторые плохие матчи. На изображениях каждая зеленая линия соединяет пару сопряженных точек. И, пожалуйста, игнорируйте красные знаки. Я не могу найти ничего плохого, может ли кто-нибудь дать мне какие-то намеки? Заранее спасибо.

ответ

1

RANSAC - всего лишь одна из надежных оценок. В принципе, можно использовать множество из них, но RANSAC показал, что он работает достаточно хорошо, пока ваши входные данные не доминируют в выбросах. Вы можете проверить другие варианты на RANSAC, такие как MSAC, MLESAC, MAPSAC и т. Д., Которые также имеют некоторые другие интересные свойства. Вы можете найти эту CVPR презентацию интересные (http://www.imgfsr.com/CVPR2011/Tutorial6/RANSAC_CVPR2011.pdf)

В зависимости от качества исходных данных, вы можете оценить оптимальное количество итераций RANSAC, как описано здесь (https://en.wikipedia.org/wiki/RANSAC#Parameters)

Опять же, это один из надежных методы оценки. Вы можете использовать другие статистические подходы, такие как моделирование ваших данных с распределением тяжелых хвостов, обрезанные наименьшие квадраты и т. Д.

В вашем коде отсутствует шаг RANSAC. RANSAC имеет в основном 2 этапа:

generate hypothesis (do a random selection of data points necessary to fit your mode: training data). 
model evaluation (evaluate your model on the rest of the points: testing data) 
iterate and choose the model that gives the lowest testing error. 
+0

Спасибо за подробное объяснение. Не 'cv :: findFundamentalMat (fp [0], fp [1], cv :: FM_RANSAC, 3, 1, mask);' выполните полный шаг RANSAC, как вы сказали? – Anonymous

+0

Ах да. Глядя на документы opencv, похоже, это так. У меня есть ощущение, что эти параметры не могут быть оптимизированы. Поэтому первое, что я хотел бы попробовать, - уменьшить Param1 от 3 до более низких значений и посмотреть, что я получаю. Я бы также установил Param2 примерно на 0.99, так как это может уменьшить количество итераций и время вычисления. Очевидность 1 кажется слишком большой. – Luca

+0

Спасибо. Я попробую. – Anonymous

0

RANSAC означает RANdom SAmple Consensus, он не удаляет выбросы, он выбирает группу точек для вычисления фундаментальной матрицы для этой группы точек. Затем вам нужно сделать репроекцию, используя базовую матрицу, только что рассчитанную с помощью RANSAC, чтобы удалить выбросы.

+0

Спасибо за помощь. Похоже, что время стоит RANSAC и перепрограммировать. Есть ли другой лучший метод? Еще раз спасибо! – Anonymous

+0

Ну, может показаться, но это не так. Репроектирование нескольких координат относительно дешево по сравнению с функциями экстракции и выполняется сотни раз во время вызова findFundamentalMat – Gilfoyle

+0

@ Гилфой, который я вижу. Благодарю. – Anonymous

0

Как и любой алгоритм, ransac не идеален. Вы можете попытаться запустить другие способные (в opencv) надежные алгоритмы, такие как LMEDS. И вы можете повторить, используя последние точки, отмеченные как inliers, в качестве входных данных для новой оценки. И вы можете изменить порог и уровень уверенности. Я предлагаю запустить ransac 1 ~ 3 раза, а затем запустить LMEDS, который не нуждается в пороге, но работает только с минимум 50% от уровня.

И, вы можете иметь проблемы геометрические порядка:

* Если базовая линия между двумя стерео слишком мал, оценка фундаментальная матрица может быть ненадежным и может быть лучше использовать findHomography() вместо этого, для вашей цели ,

* Если у ваших изображений есть искажение барреля/пинкушина, они не соответствуют эпиполярной геометрии, а фундаментальная матрица не является правильной математической моделью для соединения матчей. В этом случае вам, возможно, придется откалибровать камеру, а затем запустить undistort(), а затем обработать выходные изображения.