OpenCV: Сравняване на множество изображения с помощта на ORB

Опитвам се да създам C++ програма, където има много изображения в списък в сравнение с едно входно изображение. Всичко работи и програмата създава DMatch съвпадения.

Сега се опитвам да определя кое от списъка с изображения, сравнено с изходното изображение, съответства най-добре. Първо се опитах да направя това просто сравнявайки колко съвпадения има между изображенията, но проблемът е, че когато генерираното изображение има много ключови точки; те също са склонни да имат много съвпадения, поне в моята програма.

И така, как мога да определя кое от масива изображения съответства най-добре на изходното изображение? Използвам този цикъл, за да определя съвпаденията, но всъщност не работи:

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);

Ако някой може да ме насочи към функциите или логиката, която трябва да използвам, ще съм много благодарен!


person tversteeg    schedule 04.03.2013    source източник
comment
Какъв е проблемът да се каже Съвпадението с най-много инлиери е моето най-добро съвпадение.?   -  person Tobias Hermann    schedule 08.03.2013
comment
Това беше и първото нещо, за което се сетих, но когато го пробвах, не получих точни резултати.   -  person tversteeg    schedule 08.03.2013
comment
Добре, така че изображенията (дори фалшивите) са доста сходни предполагам. Каква е точността, ако вземете средното разстояние на всички съвпадения или на всички инлиери? Можете ли да публикувате примерни снимки, когато това не работи?   -  person Tobias Hermann    schedule 08.03.2013
comment
Намерихте ли приемливо решение след този пост? Много се интересувам от решение, имам подобен проблем за бързо разрешаване.   -  person Spawnrider    schedule 23.11.2013
comment
Не, не наистина, успях да го накарам да работи, но беше наистина бавен за множество изображения и не се мащабира добре. Затова избрах да използвам решение на трета страна.   -  person tversteeg    schedule 23.11.2013
comment
Какво имате предвид под решение на трета страна? Бихте ли ми дали име на решение?   -  person Spawnrider    schedule 26.11.2013
comment
Използвах Vuforia от Quelcomm, те предоставят услуга, която използва собствени сървъри за IR.   -  person tversteeg    schedule 26.11.2013


Отговори (4)


Зависи какво е изображението в списъка. Не можете да имате едно решение за всеки проблем със зрението в света. Например, проектът, върху който работя, трябва да разпознава материал в картини на стени. Не можете просто да го сравните с различна картина на стена с различен материал и да се надявате да получите съвпадение.

В моя случай трябваше да създам дескриптори. Дескрипторите са алгоритъм, който извежда стойност, която може да бъде сравнена с друга стойност на друга картина. Има много дескриптори, които вече са налични в openCV като LBP, SURF и т.н. Казано по-просто, вие вече не сравнявате изображението, сравнявате изходната стойност на дескриптора на изображение 1 със стойността на дескриптора на всички изображение в списъка.

Трябва да вземете дескрипторите, които вашите очи/мозък използват, за да намерите съвпадение в реалния живот. Например, ако съответствието се основава на цвят, можете да използвате CLD или DCD. Ако съвпадението се основава на текстура, използвайте LBP. Можете също така да направите като мен в моя проект и да използвате много дескриптори и да използвате машинно обучение с обучени алгоритми за данни, за да намерите най-доброто съвпадение.

Така че, за да обобщим, няма сребърен куршум, който може да реши всички проблеми със зрението. Трябва да адаптирате решението си към проблема.

Дано помогне!

person Jean-François Côté    schedule 12.03.2013

Няма ясен отговор. За по-добри резултати трябва да приложите някакъв вид трансформация и да направите групиране върху трансформираната карта, вместо просто да сумирате разстоянията. Това е трудно и дори може да се публикува.

В противен случай ще трябва да използвате по-практични техники като размерно и хистограмно филтриране. Можете да разгледате stitcher на OpenCV, да изолирате модул, който ви интересува, и персонализирайте изходния код според вашите нужди.

person LovaBill    schedule 12.03.2013

Трябва да изберете само наистина стабилни съответствия. Бих препоръчал да прочетете: OpenCV 2 Computer Vision Application Programming Cookbook - Chapter 9 - Matching images using random sample consensus (http://opencv-cookbook.googlecode.com/svn/trunk/Chapter%2009/).

person Balázs Szántó    schedule 11.03.2013
comment
връзката е мъртва - person Sabito 錆兎; 17.09.2020

кратко търсене на вашия проблем ми даде следния запис в секциите за отговори на opencv:

/Форум за CV отговори

което изглежда дава отговор на въпроса, който изглежда имате. За да филтрирате резултатите, които получавате, както е предложено в отговора, бих разгледал алгоритъма RANSAC, за да намеря най-добрите резултати в избрания от вас мач.

Уикипедия с описание на RANSAC

Поне това трябва да ви насочи в правилната посока.

person Xtroce    schedule 12.03.2013
comment
Ако погледнете моя код, можете да видите, че вече използвам RANSAC. - person tversteeg; 12.03.2013