2013-03-04 16 views
6

하나의 입력 이미지와 비교하여 목록에 많은 이미지가있는 C++ 프로그램을 만들려고합니다. 나는 모든 것을 작동 시켰고 프로그램은 DMatch과 일치합니다.OpenCV : ORB를 사용하여 여러 이미지 비교

이제 소스 이미지와 비교되는 이미지 목록 중 가장 일치하는 이미지를 결정하려고합니다. 나는 처음에는 얼마나 많은 일치를 이미지와 비교하는지에 대해서 먼저 시도했지만, 문제는 생성 된 이미지에 많은 키 포인트가있을 때입니다. 그들은 또한 내 프로그램에서 적어도 많은 성냥을 가지고있는 경향이 있습니다.

그럼 소스 이미지와 가장 일치하는 이미지 배열을 어떻게 확인할 수 있습니까? 나는 일치를 확인하려면이 루프를 사용하고 있지만 정말 작동하지 않습니다 : 누군가가 기능이나 논리에 날 지점 수 있다면

vector< vector<DMatch> > filteredMatches; 
vector<int> goodIds; 
Ptr<DescriptorMatcher> matcher(new BFMatcher(NORM_HAMMING, false)); 

printf("bad matches: "); 

for(size_t i = 0; i < images.size();i++){ 
    vector<DMatch> matches, good_matches; 

    matcher->clear(); 
    matcher->match(images[i], tex_des, matches); 
    if(matches.size() < 8){ 
     printf("F%d,", (int)i + 1); 
     continue; 
    } 

    double min_dist = 100; 

    for(size_t j = 0; j < matches.size(); j++){ 
     double dist = matches[j].distance; 
     if(dist < min_dist) 
      min_dist = dist; 
    } 

    if(min_dist > 50.0){ 
     printf("D%d,", (int)i + 1); 
     continue; 
    } 

    double good_dist = min_dist * 3; 
    for(size_t j = 0; j < matches.size(); j++){ 
     if(matches[j].distance < good_dist) 
      good_matches.push_back(matches[j]); 
    } 

    size_t size = good_matches.size(); 
    if(size < 8){ 
     printf("M%d,", (int)i + 1); 
     continue; 
    } 

    vector<Point2f> srcPoints(size); 
    vector<Point2f> dstPoints(size); 

    for(size_t j = 0; j < size; j++){ 
     srcPoints[j] = destination[good_matches[j].trainIdx].pt;  
     dstPoints[j] = keyPoints[i][good_matches[j].queryIdx].pt; 
    } 

    vector<unsigned char> inliersMask(srcPoints.size()); 
    Mat H = findHomography(srcPoints, dstPoints, CV_FM_RANSAC, 3.0, inliersMask); 

    vector<DMatch> inliers; 
    for(size_t j = 0; j < inliersMask.size(); j++){ 
     if(inliersMask[j]){ 
      inliers.push_back(good_matches[j]); 
     } 
    } 
    if(inliers.size() < 4){ 
     printf("S%d,", (int)i + 1); 
     continue; 
    } 

    filteredMatches.push_back(inliers); 
    goodIds.push_back((int)i); 

    H.release(); 
} 

printf(" good matches: "); 

int best = -1; 
int amount = 0; 
for(size_t i = 0; i < filteredMatches.size(); i++){ 
    int size = (int)filteredMatches.at(i).size(); 
    if(size < 8) continue; 

    printf("%d,", goodIds[i] + 1); 

    if(amount < size){ 
     amount = size; 
     best = i; 
    } 
} 

if(best >= 0) printf(" best match on image: %d, keypoints: %d, ", goodIds[best] + 1, amount); 

나는 내가 대단히 감사하겠습니다 사용해야합니다!

+0

"가장 많은 inliers와 일치하는 것이 가장 적합합니다."라는 문구는 무엇입니까? –

+0

그게 내가 생각한 첫 번째 문제 였지만, 시도했을 때 정확한 결과를 얻지 못했습니다. – tversteeg

+0

좋아, 그래서 이미지 (심지어 거짓 것들) 꽤 비슷합니다. 모든 일치 또는 모든 inliers의 평균 거리를 취하면 정확도는 어떻게됩니까? 이것이 실패한 예시 사진을 게시 할 수 있습니까? –

답변

0

문제에 대한 간단한 검색은 OpenCV의 응답 섹션의 항목을 다음과 같이 저를 공급 :

질문에 대한 답변을 제공 할 것

/CV Answer forum

당신이있을 것 같다. 답안에서 제안한 결과를 필터링하려면 RANSAC 알고리즘을 살펴보고 일치 항목에서 최상의 결과를 찾으십시오.

RANSAC desctiption Wikipedia

은 적어도이 올바른 방향을 가리켜 야합니다.

+0

내 코드를 보면 이미 RANSAC을 사용하고있는 것을 볼 수 있습니다. – tversteeg

0

목록의 이미지가 무엇인가에 따라 다릅니다. 전 세계의 모든 시력 문제에 대해 하나의 솔루션을 가질 수는 없습니다. 예를 들어, 제가 작업하는 프로젝트는 벽 그림에서 재료를 인식해야합니다. 다른 소재로 다른 벽면 사진과 비교할 수 없으며 일치를 얻을 수 있기를 바랍니다.

제 경우에는 설명자를 작성해야했습니다. Descriptors은 다른 그림의 다른 값과 비교할 수있는 값을 출력하는 알고리즘입니다. 이미 LBP, SURF 등과 같이 openCV에서 사용할 수있는 많은 기술자가 있습니다. 간단히 말하면 이미지를 더 이상 비교하지 않고 이미지 1의 디스크립터 출력 값을 모든 디스크립터의 디스크립터 값과 비교합니다. 목록의 이미지.

실생활에서 일치하는 것을 찾으려면 눈/두뇌에서 사용하는 설명자를 선택해야합니다. 예를 들어 일치가 색상을 기반으로하는 경우 CLD 또는 DCD를 사용할 수 있습니다. 매칭이 텍스처를 기반으로하는 경우 LBP를 사용합니다. 또한 프로젝트에서했던 것처럼 디스크립터를 많이 사용하고 훈련 된 데이터 알고리즘을 사용하여 기계 학습을 사용하여 가장 일치하는 것을 찾을 수 있습니다.

요약하면, 모든 시력 문제를 해결할 수있는 은색 총알은 없습니다. 문제에 솔루션을 적용해야합니다.

희망이 있습니다.

1

직접적인 대답은 없습니다. 더 나은 결과를 얻으려면 거리를 합산하는 대신 변환 된 맵에서 일종의 변환을 수행하고 클러스터링을 수행해야합니다. 어렵고 심지어 publishable입니다.

그렇지 않으면 차원 및 막대 그래프 필터링과 같은보다 실용적인 기술을 사용해야합니다. OpenCV의 stitcher을보고 관심있는 모듈을 격리하고 필요에 따라 소스 코드를 사용자 정의 할 수 있습니다.