2016-06-15 7 views
0

SIFT를 사용하여 두 이미지간에 좋은 일치가없는 이유가 궁금합니다. 일치하는 이미지는 다음과 같습니다. enter image description here 원본 이미지두 이미지 사이에서 SIFT를 사용하여 일치하는 기능 지점

enter image description here

enter image description here

내 프로그램은 다음과 같다 있습니다.

int imagematching(Mat &img1, Mat & img2, std::vector<Point2f> &first_keypoints, std::vector<Point2f> &second_keypoints){ 
    int max_keypoints = 500; 

    Ptr<SIFT> detector = SIFT::create(); 
    Ptr<SIFT> extractor = SIFT::create(); 

    //--Step 1: Key point detection 
    std::vector<KeyPoint> keypoints1, keypoints2; 
    //-- Step 2: Calculate descriptors (feature vectors) 
    Mat descriptors1, descriptors2; 

    detector->detect(img1, keypoints1); 
    detector->detect(img2, keypoints2); 

    extractor->compute(img1, keypoints1, descriptors1); 
    extractor->compute(img2, keypoints2, descriptors2);  

    FlannBasedMatcher matcher; 


    vector<DMatch> matches; 
    matcher.match(descriptors1, descriptors2, matches); 

    double max_dist = 0; double min_dist = 999999; 

    //-- 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; 
    } 

    printf("-- Max dist : %f \n", max_dist); 
    printf("-- Min dist : %f \n", min_dist); 
    //-- Draw only "good" matches (i.e. whose distance is less than 3*min_dist) 
    std::vector<DMatch> good_matches; 

    for(int i = 0; i < descriptors1.rows; i++) 
    { 
     if(matches[i].distance < 3*min_dist) 
     { good_matches.push_back(matches[i]); } 
    } 
    matches.clear(); 

    Mat img_matches; 
    drawMatches(img1, keypoints1, img2, keypoints2, 
       good_matches, img_matches, Scalar::all(-1), Scalar::all(-1), 
       vector<char>(), DrawMatchesFlags::NOT_DRAW_SINGLE_POINTS); 

    descriptors1.release(); 
    descriptors2.release(); 

    //-- Localize the object 
    //std::vector<Point2f> first_keypoints; 
    //std::vector<Point2f> second_keypoints; 

    for(int i = 0; i < good_matches.size(); i++) 
    { 
     //cout << i << " :"; 
     //-- Get the keypoints from the good matches 
     if(keypoints1[ good_matches[i].queryIdx ].pt.x > 0 && keypoints1[ good_matches[i].queryIdx ].pt.y > 0 
       && keypoints2[ good_matches[i].trainIdx ].pt.x > 0 && keypoints2[ good_matches[i].trainIdx ].pt.y > 0){ 
      first_keypoints.push_back(keypoints1[ good_matches[i].queryIdx ].pt); 
      //cout << "first point" << keypoints1[ good_matches[i].queryIdx ].pt << endl; 

      second_keypoints.push_back(keypoints2[ good_matches[i].trainIdx ].pt); 
      //cout << "second point" << keypoints2[ good_matches[i].trainIdx ].pt << endl; 
     } 
    } 
    keypoints1.clear(); 
    keypoints2.clear(); 
    good_matches.clear(); 
    //-- Show detected matches 
    imshow("Good Matches & Object detection", img_matches); 
    waitKey(0); 

    return SUCCESS; 
} 
+0

SIFT/SURF/etc. 일반적으로 선행 적으로 불변 적이 지 않습니다. 사소한 각도에서도 작동하지만 오브젝트는 90 ° 회전합니다. 일반적으로 이런 종류의 물체 인식을 위해서는 같은 각도의 물체를 여러 번 표현한 데이터베이스를 사용하십시오. 정면에서 동일한 물체를 포착하고 그 물체를 두 이미지와 일치 시키려고 할 수 있습니까? 어쩌면 45 ° 각도가 이미 괜찮은 것일 수도 있습니다. – Micka

답변

0

SIFT는 회전 불변이지만 확실히 투시 불변의 것은 아닙니다. 이미지를 다른 원근법과 비교할 수 있도록 일부 기계 학습 (어쩌면 SVM)을 추가해야합니다. SIFT 기능만으로는 충분하지 않습니다.

+0

기계 학습은 이미지가 1 개인 경우에만 트릭을 수행하지 않습니다. 추가 정보 *가 필요합니다. @Micka가 다른 관점의 이미지를 사용하거나 객체의 3D 모델을 파생/모델링하여 제안했습니다 (ML은 마술을 할 수 없습니다.) – geekoverdose

+0

예, 그 점이 있습니다. –