215 lines
		
	
	
		
			7.4 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			215 lines
		
	
	
		
			7.4 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
/*M///////////////////////////////////////////////////////////////////////////////////////
 | 
						|
//
 | 
						|
//  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
 | 
						|
//
 | 
						|
//  By downloading, copying, installing or using the software you agree to this license.
 | 
						|
//  If you do not agree to this license, do not download, install,
 | 
						|
//  copy or use the software.
 | 
						|
//
 | 
						|
// This file originates from the openFABMAP project:
 | 
						|
// [http://code.google.com/p/openfabmap/]
 | 
						|
//
 | 
						|
// For published work which uses all or part of OpenFABMAP, please cite:
 | 
						|
// [http://ieeexplore.ieee.org/xpl/articleDetails.jsp?arnumber=6224843]
 | 
						|
//
 | 
						|
// Original Algorithm by Mark Cummins and Paul Newman:
 | 
						|
// [http://ijr.sagepub.com/content/27/6/647.short]
 | 
						|
// [http://ieeexplore.ieee.org/xpl/articleDetails.jsp?arnumber=5613942]
 | 
						|
// [http://ijr.sagepub.com/content/30/9/1100.abstract]
 | 
						|
//
 | 
						|
//                           License Agreement
 | 
						|
//
 | 
						|
// Copyright (C) 2012 Arren Glover [aj.glover@qut.edu.au] and
 | 
						|
//                    Will Maddern [w.maddern@qut.edu.au], all rights reserved.
 | 
						|
//
 | 
						|
//
 | 
						|
// Redistribution and use in source and binary forms, with or without modification,
 | 
						|
// are permitted provided that the following conditions are met:
 | 
						|
//
 | 
						|
//   * Redistribution's of source code must retain the above copyright notice,
 | 
						|
//     this list of conditions and the following disclaimer.
 | 
						|
//
 | 
						|
//   * Redistribution's in binary form must reproduce the above copyright notice,
 | 
						|
//     this list of conditions and the following disclaimer in the documentation
 | 
						|
//     and/or other materials provided with the distribution.
 | 
						|
//
 | 
						|
//   * The name of the copyright holders may not be used to endorse or promote products
 | 
						|
//     derived from this software without specific prior written permission.
 | 
						|
//
 | 
						|
// This software is provided by the copyright holders and contributors "as is" and
 | 
						|
// any express or implied warranties, including, but not limited to, the implied
 | 
						|
// warranties of merchantability and fitness for a particular purpose are disclaimed.
 | 
						|
// In no event shall the Intel Corporation or contributors be liable for any direct,
 | 
						|
// indirect, incidental, special, exemplary, or consequential damages
 | 
						|
// (including, but not limited to, procurement of substitute goods or services;
 | 
						|
// loss of use, data, or profits; or business interruption) however caused
 | 
						|
// and on any theory of liability, whether in contract, strict liability,
 | 
						|
// or tort (including negligence or otherwise) arising in any way out of
 | 
						|
// the use of this software, even if advised of the possibility of such damage.
 | 
						|
//
 | 
						|
//M*/
 | 
						|
 | 
						|
 | 
						|
#include "opencv2/opencv.hpp"
 | 
						|
#include "opencv2/nonfree/nonfree.hpp"
 | 
						|
 | 
						|
using namespace cv;
 | 
						|
using namespace std;
 | 
						|
 | 
						|
int main(int argc, char * argv[]) {
 | 
						|
 | 
						|
    /*
 | 
						|
 | 
						|
    Note: the vocabulary and training data is specifically made for this openCV
 | 
						|
    example. It is not reccomended for use with other datasets as it is
 | 
						|
    intentionally small to reduce baggage in the openCV project.
 | 
						|
 | 
						|
    A new vocabulary can be generated using the supplied BOWMSCtrainer (or other
 | 
						|
    clustering method such as K-means
 | 
						|
 | 
						|
    New training data can be generated by extracting bag-of-words using the
 | 
						|
    openCV BOWImgDescriptorExtractor class.
 | 
						|
 | 
						|
    vocabulary, chow-liu tree, training data, and test data can all be saved and
 | 
						|
    loaded using openCV's FileStorage class and it is not necessary to generate
 | 
						|
    data each time as done in this example
 | 
						|
 | 
						|
    */
 | 
						|
 | 
						|
    cout << "This sample program demonstrates the FAB-MAP image matching "
 | 
						|
        "algorithm" << endl << endl;
 | 
						|
 | 
						|
    string dataDir;
 | 
						|
    if (argc == 1) {
 | 
						|
        dataDir = "fabmap/";
 | 
						|
    } else if (argc == 2) {
 | 
						|
        dataDir = string(argv[1]);
 | 
						|
        dataDir += "/";
 | 
						|
    } else {
 | 
						|
        //incorrect arguments
 | 
						|
        cout << "Usage: fabmap_sample <sample data directory>" <<
 | 
						|
            endl;
 | 
						|
        return -1;
 | 
						|
    }
 | 
						|
 | 
						|
    FileStorage fs;
 | 
						|
 | 
						|
    //load/generate vocab
 | 
						|
    cout << "Loading Vocabulary: " <<
 | 
						|
        dataDir + string("vocab_small.yml") << endl << endl;
 | 
						|
    fs.open(dataDir + string("vocab_small.yml"), FileStorage::READ);
 | 
						|
    Mat vocab;
 | 
						|
    fs["Vocabulary"] >> vocab;
 | 
						|
    if (vocab.empty()) {
 | 
						|
        cerr << "Vocabulary not found" << endl;
 | 
						|
        return -1;
 | 
						|
    }
 | 
						|
    fs.release();
 | 
						|
 | 
						|
    //load/generate training data
 | 
						|
 | 
						|
    cout << "Loading Training Data: " <<
 | 
						|
        dataDir + string("train_data_small.yml") << endl << endl;
 | 
						|
    fs.open(dataDir + string("train_data_small.yml"), FileStorage::READ);
 | 
						|
    Mat trainData;
 | 
						|
    fs["BOWImageDescs"] >> trainData;
 | 
						|
    if (trainData.empty()) {
 | 
						|
        cerr << "Training Data not found" << endl;
 | 
						|
        return -1;
 | 
						|
    }
 | 
						|
    fs.release();
 | 
						|
 | 
						|
    //create Chow-liu tree
 | 
						|
    cout << "Making Chow-Liu Tree from training data" << endl <<
 | 
						|
        endl;
 | 
						|
    of2::ChowLiuTree treeBuilder;
 | 
						|
    treeBuilder.add(trainData);
 | 
						|
    Mat tree = treeBuilder.make();
 | 
						|
 | 
						|
    //generate test data
 | 
						|
    cout << "Extracting Test Data from images" << endl <<
 | 
						|
        endl;
 | 
						|
    Ptr<FeatureDetector> detector =
 | 
						|
        new DynamicAdaptedFeatureDetector(
 | 
						|
        AdjusterAdapter::create("STAR"), 130, 150, 5);
 | 
						|
    Ptr<DescriptorExtractor> extractor =
 | 
						|
        new SurfDescriptorExtractor(1000, 4, 2, false, true);
 | 
						|
    Ptr<DescriptorMatcher> matcher =
 | 
						|
        DescriptorMatcher::create("FlannBased");
 | 
						|
 | 
						|
    BOWImgDescriptorExtractor bide(extractor, matcher);
 | 
						|
    bide.setVocabulary(vocab);
 | 
						|
 | 
						|
    vector<string> imageNames;
 | 
						|
    imageNames.push_back(string("stlucia_test_small0000.jpeg"));
 | 
						|
    imageNames.push_back(string("stlucia_test_small0001.jpeg"));
 | 
						|
    imageNames.push_back(string("stlucia_test_small0002.jpeg"));
 | 
						|
    imageNames.push_back(string("stlucia_test_small0003.jpeg"));
 | 
						|
    imageNames.push_back(string("stlucia_test_small0004.jpeg"));
 | 
						|
    imageNames.push_back(string("stlucia_test_small0005.jpeg"));
 | 
						|
    imageNames.push_back(string("stlucia_test_small0006.jpeg"));
 | 
						|
    imageNames.push_back(string("stlucia_test_small0007.jpeg"));
 | 
						|
    imageNames.push_back(string("stlucia_test_small0008.jpeg"));
 | 
						|
    imageNames.push_back(string("stlucia_test_small0009.jpeg"));
 | 
						|
 | 
						|
    Mat testData;
 | 
						|
    Mat frame;
 | 
						|
    Mat bow;
 | 
						|
    vector<KeyPoint> kpts;
 | 
						|
 | 
						|
    for(size_t i = 0; i < imageNames.size(); i++) {
 | 
						|
        cout << dataDir + imageNames[i] << endl;
 | 
						|
        frame = imread(dataDir + imageNames[i]);
 | 
						|
        if(frame.empty()) {
 | 
						|
            cerr << "Test images not found" << endl;
 | 
						|
            return -1;
 | 
						|
        }
 | 
						|
 | 
						|
        detector->detect(frame, kpts);
 | 
						|
 | 
						|
        bide.compute(frame, kpts, bow);
 | 
						|
 | 
						|
        testData.push_back(bow);
 | 
						|
 | 
						|
        drawKeypoints(frame, kpts, frame);
 | 
						|
        imshow(imageNames[i], frame);
 | 
						|
        waitKey(10);
 | 
						|
    }
 | 
						|
 | 
						|
    //run fabmap
 | 
						|
    cout << "Running FAB-MAP algorithm" << endl <<
 | 
						|
        endl;
 | 
						|
    Ptr<of2::FabMap> fabmap;
 | 
						|
 | 
						|
    fabmap = new of2::FabMap2(tree, 0.39, 0, of2::FabMap::SAMPLED |
 | 
						|
        of2::FabMap::CHOW_LIU);
 | 
						|
    fabmap->addTraining(trainData);
 | 
						|
 | 
						|
    vector<of2::IMatch> matches;
 | 
						|
    fabmap->compare(testData, matches, true);
 | 
						|
 | 
						|
    //display output
 | 
						|
    Mat result_small = Mat::zeros(10, 10, CV_8UC1);
 | 
						|
    vector<of2::IMatch>::iterator l;
 | 
						|
 | 
						|
    for(l = matches.begin(); l != matches.end(); l++) {
 | 
						|
            if(l->imgIdx < 0) {
 | 
						|
                result_small.at<char>(l->queryIdx, l->queryIdx) =
 | 
						|
                    (char)(l->match*255);
 | 
						|
 | 
						|
            } else {
 | 
						|
                result_small.at<char>(l->queryIdx, l->imgIdx) =
 | 
						|
                    (char)(l->match*255);
 | 
						|
            }
 | 
						|
    }
 | 
						|
 | 
						|
    Mat result_large(100, 100, CV_8UC1);
 | 
						|
    resize(result_small, result_large, Size(500, 500), 0, 0, CV_INTER_NN);
 | 
						|
 | 
						|
    cout << endl << "Press any key to exit" << endl;
 | 
						|
    imshow("Confusion Matrix", result_large);
 | 
						|
    waitKey();
 | 
						|
 | 
						|
    return 0;
 | 
						|
}
 |