我正在研究一個項目,我將使用單應作爲分類器中的特徵。我的問題是自動計算單應性,我使用SIFT描述符來找出兩幅圖像之間的點來計算單應性,但SIFT給我的結果很差,因此我不能在我的工作中使用它們。SIFT匹配給出了非常差的結果
我正在使用OpenCV 2.4.3。
起初我使用SURF,但我有類似的結果,我決定使用更慢但更精確的SIFT。我的第一個猜測是,我的數據集的圖像分辨率太低,但我運行我的算法在一個最先進的數據集(指向04),我獲得了幾乎相同的結果,所以問題在於我所做的而不是在我的數據集中。
在每個圖像中找到的SIFT關鍵點之間的匹配是使用FlannBased匹配器完成的,我嘗試了BruteForce,但結果幾乎相同。
這是(來自指點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);
,關於如何提高匹配性能的任何幫助將是非常感謝,謝謝。
如果對'FeatureDetector :: create()'使用''DENSE''會怎麼樣? – William
我認爲基本的SIFT無法處理您期望的扭曲。像PSIFT可能是值得研究的http://www.sciencedirect.com/science/article/pii/S0165168413001503 – Bull
可悲的是,沒有顯着改善使用「密集」在'create()' – powder