SIFT сопоставление дает очень плохие результаты

Я работаю над проектом, в котором я буду использовать гомографию в качестве функций в классификаторе. Моя проблема заключается в автоматическом расчете гомографий, я использую SIFT-дескрипторы, чтобы найти точки между двумя изображениями, на которых можно рассчитывать гомографию, но SIFT дает мне очень плохие результаты, поэтому я не могу использовать их в своей работе.

Я использую OpenCV 2.4.3.

Сначала я использовал SURF, но у меня были похожие результаты, и я решил использовать SIFT, который медленнее, но точнее. Моим первым предположением было то, что разрешение изображения в моем наборе данных было слишком низким, но я запустил свой алгоритм на современном наборе данных (Pointing 04), и я получил почти те же результаты, поэтому проблема заключается в том, что я делаю и не в моем наборе данных.

Совпадение ключевых точек SIFT, найденных на каждом изображении, выполняется с помощью средства сопоставления FlannBase, я попробовал BruteForce, но результаты снова оказались практически такими же.

Это пример совпадения, которое я нашел (изображение из набора данных Pointing 04)
Совпадения моего алгоритма

Изображение выше показывает, насколько плохое совпадение найдено с моей программой. Только 1 балл — правильное совпадение. Мне нужно (по крайней мере) 4 правильных матча для того, что я должен сделать.

Вот код, который я использую:

Это функция, которая извлекает дескрипторы SIFT из каждого изображения

void extract_sift(const Mat &img, vector<KeyPoint> &keypoints, Mat &descriptors, Rect* face_rec) {

// Create masks for ROI on the original image
Mat mask1 = Mat::zeros(img.size(), CV_8U);  // type of mask is CV_8U

Mat roi1(mask1, *face_rec);
roi1 = Scalar(255, 255, 255);

// Extracts keypoints in ROIs only
Ptr<DescriptorExtractor> featExtractor;
Ptr<FeatureDetector> featDetector;
Ptr<DescriptorMatcher> featMatcher;

featExtractor = new SIFT();
featDetector = FeatureDetector::create("SIFT");

featDetector->detect(img,keypoints,mask1);
featExtractor->compute(img,keypoints,descriptors);

}

Это функция, которая соответствует дескрипторам двух изображений

void match_sift(const Mat &img1, const Mat &img2, const vector<KeyPoint> &kp1,
const vector<KeyPoint> &kp2, const Mat &descriptors1, const Mat &descriptors2,
vector<Point2f> &p_im1, vector<Point2f> &p_im2) {

//  Matching descriptor vectors using FLANN matcher
Ptr<DescriptorMatcher> matcher = DescriptorMatcher::create("FlannBased");
std::vector< DMatch > matches;
matcher->match( descriptors1, descriptors2, matches );

double max_dist = 0; double min_dist = 100;

// Quick calculation of max and min distances between keypoints
for( int i = 0; i < descriptors1.rows; ++i ){
double dist = matches[i].distance;
if( dist < min_dist ) min_dist = dist;
if( dist > max_dist ) max_dist = dist;
}

// Draw only the 4 best matches
std::vector< DMatch > good_matches;

// XXX: DMatch has no sort method, maybe a more efficent min extraction algorithm can be used here?
double min=matches[0].distance;
int min_i = 0;
for( int i = 0; i < (matches.size()>4?4:matches.size()); ++i ) {
for(int j=0;j<matches.size();++j)
if(matches[j].distance < min) {
min = matches[j].distance;
min_i = j;
}
good_matches.push_back( matches[min_i]);
matches.erase(matches.begin() + min_i);
min=matches[0].distance;
min_i = 0;
}

Mat img_matches;
drawMatches( img1, kp1, img2, kp2,
good_matches, img_matches, Scalar::all(-1), Scalar::all(-1),
vector<char>(), DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS );
imwrite("imgMatch.jpeg",img_matches);
imshow("",img_matches);
waitKey();

for( int i = 0; i < good_matches.size(); i++ )
{
// Get the points from the best matches
p_im1.push_back( kp1[ good_matches[i].queryIdx ].pt );
p_im2.push_back( kp2[ good_matches[i].trainIdx ].pt );
}
}

И эти функции называются здесь:

extract_sift(dataset[i].img,dataset[i].keypoints,dataset[i].descriptors,face_rec);
[…]
//  Extract keypoints from i+1 image and calculate homography
extract_sift(dataset[i+1].img,dataset[i+1].keypoints,dataset[i+1].descriptors,face_rec);
dataset[front].points_r.clear(); // XXX: dunno if clearing the points every time is the best way to do it..
match_sift(dataset[front].img,dataset[i+1].img,dataset[front].keypoints,dataset[i+1].keypoints,
dataset[front].descriptors,dataset[i+1].descriptors,dataset[front].points_r,dataset[i+1].points_r);

dataset[i+1].H = findHomography(dataset[front].points_r,dataset[i+1].points_r, RANSAC);

Спасибо за любую помощь в улучшении производительности сопоставления.

4

Решение

Вы, очевидно, используете «лучшие четыре точки» в своем коде w.r.t. дистанция спичек. Другими словами, вы считаете, что совпадение действительно, если оба дескриптора действительно похожи. Я считаю, что это неправильно. Вы пытались нарисовать все спички? Многие из них должны быть неправы, но многие должны быть хорошими.

Расстояние матча просто говорит о том, насколько похожи обе точки. Это не говорит о том, является ли соответствие геометрически согласованным. Выбор лучших совпадений должен определенно учитывать геометрию.

Вот как бы я это сделал:

  1. Определить углы (вы уже делаете это)
  2. Найти matches (вы уже делаете это)
  3. Попробуйте найти преобразование гомографии между двумя изображениями, используя matches (не фильтруйте их раньше!) используя findHomography(...)
  4. findHomography(...) скажу вам, какие являются внутренностями. Это ваши good_matches,
5

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]