2013-07-09 36 views
4

我正在研究一個項目,我將使用單應作爲分類器中的特徵。我的問題是自動計算單應性,我使用SIFT描述符來找出兩幅圖像之間的點來計算單應性,但SIFT給我的結果很差,因此我不能在我的工作中使用它們。SIFT匹配給出了非常差的結果

我正在使用OpenCV 2.4.3。

起初我使用SURF,但我有類似的結果,我決定使用更慢但更精確的SIFT。我的第一個猜測是,我的數據集的圖像分辨率太低,但我運行我的算法在一個最先進的數據集(指向04),我獲得了幾乎相同的結果,所以問題在於我所做的而不是在我的數據集中。

在每個圖像中找到的SIFT關鍵點之間的匹配是使用FlannBased匹配器完成的,我嘗試了BruteForce,但結果幾乎相同。

這是(來自指點04數據集圖像)的匹配,我發現的一個例子 Matches of my algorithm

上述圖像顯示如何差是與我的程序中找到匹配。只有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); 

,關於如何提高匹配性能的任何幫助將是非常感謝,謝謝。

+0

如果對'FeatureDetector :: create()'使用''DENSE''會怎麼樣? – William

+0

我認爲基本的SIFT無法處理您期望的扭曲。像PSIFT可能是值得研究的http://www.sciencedirect.com/science/article/pii/S0165168413001503 – Bull

+0

可悲的是,沒有顯着改善使用「密集」在'create()' – powder

回答

5

您顯然在代碼w.r.t中使用了「最佳四點」。比賽的距離。換句話說,如果兩個描述符都非常相似,則認爲匹配是有效的。我相信這是錯誤的。你試圖畫出所有的比賽嗎?他們中的許多人應該是錯的,但許多人也應該是好的。

比賽的距離只是說明兩點之間的相似程度。這並不能說明比賽是否在幾何上是連貫的。選擇最佳匹配應該肯定考慮幾何。

這裏是我會怎麼做:

  1. 檢測角落(你已經這樣做)
  2. 找到matches(你已經這樣做)
  3. 試圖找到兩個圖像之間的單應變換通過使用matches(以前不要過濾它們!)使用findHomography(...)
  4. findHomography(...)會告訴你哪些是inliers。那些是你的good_matches
+1

我認爲通過這樣做我'已經稍微提高了精度,謝謝。儘管我現在有更精確的觀點,但我的分類結果仍然非常差(準確性約爲50%)。雖然我開始認爲問題在於單應性,但如果單個錯誤點被認爲是內部函數,則單應性矩陣會發生很大變化,而我的分類器會將H放在錯誤的類中。 – powder

+2

您要求使用單應性變換進行匹配。分類是另一個問題... – JonesV

相關問題