knnMatch с k = 2 возвращает 0 ближайшего соседа даже с обученными изображениями

Я в основном извлекаю много ключевых точек с помощью SURF из похожих изображений и добавляю их в BFMatcher(NORM_L2)

Во время выполнения может случиться так, что я добавлю новые ключевые точки в свой сопоставитель с помощью matcher->add(myNewDescriptors);

Теперь, когда я добавил изображение только с 1 ключевой точкой/дескриптором и использую knnMatch, он не возвращает совпадений:

matcher->knnMatch(queryDesc,matches,2);

Через некоторое время я получаю вектор с 0 ближайшим соседом:

for(auto i = 0; i <matches.size(); i++) {
    cout << "matches size: "<<matches[i].size()<<endl;
    //> PRINTS: "matches size: 0"

Это происходит только тогда, когда я вставил изображение только с 1 ключевой точкой/дескриптором. До того, как knnMatch работает нормально.

Я попытался проверить, содержит ли matcher.getTrainDescriptors(); мои дескрипторы, и фактически он содержит все. Чтобы проверить это, если я сделаю:

cout << matcher->getTrainDescriptors().at(0).size(); // (Get the size of the descriptors Mat associated to the first training image)

Я получаю: [128 x 32]. Это означает, что дескрипторы есть, но knnMatches возвращает пустой вектор.

Также обратите внимание, что если я заменяю .knnMatch простым .match, сопоставитель возвращает все DMatches нормально! Код не работает только с knnMatch

- OpenCV: 2.4.5


person dynamic    schedule 01.06.2013    source источник


Ответы (1)


Я думаю, это ошибка. Я написал простой скрипт, чтобы проверить это. Пожалуйста, если кто-то хочет подтвердить, это поможет.

Этот скрипт извлекает первые 100 ключевых точек на изображении, а затем извлекает 1 ключевую точку. Оба набора дескрипторов хранятся внутри сопоставителя с расширением .add.

Затем, если вы запустите его, вы увидите, что использование кода .match работает. Используя knnMatch, сопоставитель ничего не возвращает:

Ptr<FeatureDetector> d = new OrbFeatureDetector();  
Ptr<DescriptorExtractor> e = new OrbDescriptorExtractor();
Ptr<DescriptorMatcher> m = new BFMatcher(NORM_HAMMING);


//> The first iteration will extract 100 keypoints and store them
//> The second iteration will extract 1 keypoint
for(int i=100;i>0;i=i-99) {
    d = new OrbFeatureDetector(i);
    Mat image = imread("train.png",0);
    vector<KeyPoint> kp;
    d->detect(image,kp);
    cout << "detected: "<<kp.size()<<endl;

    Mat desc;
    e->compute(image,kp,desc);
    cout << "descriptor size: "<<desc.size()<<endl;

    vector<Mat> addDesc;
    addDesc.push_back(desc);
    m->add( addDesc );

}

//> Test match and knnMatch
d = new OrbFeatureDetector(100);
Mat image = imread("query.png",0);
vector<KeyPoint> kp;

d->detect(image,kp);
Mat queryDesc;
e->compute(image,kp,queryDesc);



vector<DMatch> matches;
m->match(queryDesc,matches);


cout << "Parsing matches: "<<matches.size()<<endl;
for(int i=0;i<matches.size();i++)
    cout << "Matches[i].distance: "<<matches[i].distance<<endl;


vector<vector<DMatch>> matches2;
m->knnMatch(queryDesc,matches2,2);


cout << "Parsing matches: "<<matches2.size()<<endl;
for(int i=0;i<matches2.size();i++)
    cout << "matches size: "<<matches2[i].size()<<endl; //> THIS SHOULDN'T OUTPUT size: 0!

С этим кодом вызов .match вернет правильный результат. Но knnMatch терпит неудачу!

person dynamic    schedule 02.06.2013
comment
У вас есть образцы train.png и query.img (я знаю, что это, вероятно, не имеет значения)? Я не смог воспроизвести поведение 0 результатов. - person cxyzs7; 04.06.2013
comment
@cxyzs7: я добавил ссылку в вопросе на свои изображения - person dynamic; 11.06.2013