Я работаю над проектом, в котором я буду использовать гомографию в качестве функций в классификаторе. Моя проблема заключается в автоматическом расчете гомографий, я использую 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);
Спасибо за любую помощь в улучшении производительности сопоставления.
Вы, очевидно, используете «лучшие четыре точки» в своем коде w.r.t. дистанция спичек. Другими словами, вы считаете, что совпадение действительно, если оба дескриптора действительно похожи. Я считаю, что это неправильно. Вы пытались нарисовать все спички? Многие из них должны быть неправы, но многие должны быть хорошими.
Расстояние матча просто говорит о том, насколько похожи обе точки. Это не говорит о том, является ли соответствие геометрически согласованным. Выбор лучших совпадений должен определенно учитывать геометрию.
Вот как бы я это сделал:
matches
(вы уже делаете это)matches
(не фильтруйте их раньше!) используя findHomography(...)
findHomography(...)
скажу вам, какие являются внутренностями. Это ваши good_matches
,Других решений пока нет …