简体   繁体   中英

image classification using SVM and BOW?

i am not too experienced with openCV. I have some images and i want to check whether they contain a sign which i am looking for or not. So, i want to use the SVM technique for which i have some code. I have understood most the parts of the code but i don't know how can i implement this code. The code has three functions ie createTrainDataUsingBow() second is int trainSVM and int svmPredict .

Problem: I know that first i have to train the SVM and then use the predict(). But, i don't understand the arguments to be passed during their call. I mean, if i create a main() then with what parameters i should call the int trainSVM .

The whole code is given below:

1. Code for createTrainDataUsingBow()

void createTrainDataUsingBow(std::vector<char*> files, cv::Mat& train, cv::Mat&        response, int label)
{
    cv::Ptr<cv::DescriptorMatcher> matcher =    cv::DescriptorMatcher::create("FlannBased");
    cv::Ptr<cv::DescriptorExtractor> extractor = new cv::SurfDescriptorExtractor();
    cv::BOWImgDescriptorExtractor dextract( extractor, matcher );
    cv::SurfFeatureDetector detector(500);

    // cluster count
    int cluster = 100;

    // create the object for the vocabulary.
    cv::BOWKMeansTrainer bow( cluster,cv::TermCriteria(CV_TERMCRIT_EPS+CV_TERMCRIT_ITER, 10, FLT_EPSILON), 1, cv::KMEANS_PP_CENTERS );

    // get SURF descriptors and add to BOW each input files
    std::vector<char*>::const_iterator file;
    for( file = files.begin(); file != files.end(); file++)
    {
        cv::Mat img = cv::imread( *file, CV_LOAD_IMAGE_GRAYSCALE );
        std::vector<cv::KeyPoint> keypoints = detector.detect( img, keypoints);
        cv::Mat descriptors;
        extractor->compute( img, keypoints, descriptors);
        if ( !descriptors.empty() ) bow.add( descriptors );
    }

    // Create the vocabulary with KMeans.
    cv::Mat vocabulary;
    vocabulary = bow.cluster();

    for( file = files.begin(); file != files.end(); file++)
    {
        // set training data using BOWImgDescriptorExtractor
        dextract.setVocabulary( vocabulary );
        std::vector<cv::KeyPoint> keypoints;
        cv::Mat img = cv::imread( *file, CV_LOAD_IMAGE_GRAYSCALE );
        detector.detect( img, keypoints);
        cv::Mat desc;
        dextract.compute( img, keypoints, desc );
        if ( !desc.empty() )
        {
            train.push_back( desc );            // update training data
            response.push_back( label );        // update response data
        }
    }
}

2. Code for trainSVM()

int trainSVM((std::vector<char*> positive, std::vector<char*> negative)
{
    // create training data
    cv::Mat train;
    cv::Mat response;
    createTrainDataUsingBow(positive, train, response, 1.0);
    createTrainDataUsingBow(negative, train, response, -1.0);

    // svm parameters
    CvTermCriteria criteria = cvTermCriteria(CV_TERMCRIT_EPS, 1000, FLT_EPSILON);
    CvSVMParams svm_param = CvSVMParams( CvSVM::C_SVC, CvSVM::RBF, 10.0, 8.0, 1.0, 10.0,     0.5, 0.1, NULL, criteria);

    // train svm
    cv::SVM svm;
    svm.train(train, response, cv::Mat(), cv::Mat(), svm_param);
    svm.save("svm-classifier.xml");

    return 0;
}

3. Code for svmPredict()

int svmPredict(const char* classifier, const char* vocaname, const char* query, const char* method)
{
    // load image
    cv::Mat img = cv::imread(query, CV_LOAD_IMAGE_GRAYSCALE);

    // load svm
    cv::SVM svm;
    svm.load(classifier);

    // declare BOWImgDescriptorExtractor
    cv::Ptr<cv::DescriptorMatcher> matcher =     cv::DescriptorMatcher::create("FlannBased");
    cv::Ptr<cv::DescriptorExtractor> extractor = new cv::SurfDescriptorExtractor();
    cv::BOWImgDescriptorExtractor dextract( extractor, matcher );

    // load vocabulary data
    cv::Mat vocabulary;
    cv::FileStorage fs( vocaname, cv::FileStorage::READ);
    fs["vocabulary data"] >> vocabulary;
    fs.release();
    if( vocabulary.empty()  ) return 1;

    // Set the vocabulary
    dextract.setVocabulary( vocabulary );
    std::vector<cv::KeyPoint> keypoints;
    detector.detect( img, keypoints);
    cv::Mat desc_bow;
    dextract.compute( img, keypoints, desc_bow );
    if( desc_bow.empty() )  return 1;

    // svm predict
    float predict = svm.predict(centroids, true);

    std::cout << predict << std::endl;

    return 0;
}

what parameters i should call the int trainSVM.

trainSVM() takes two char* vectors which are lists of names of image files for the positive and negative samples respectively. It would probably best to make a file containing a list of positive image filenames, and the same for negatives, and to read those in.

BTW, this line has a syntax error:

int trainSVM((std::vector<char*> positive, std::vector<char*> negative)

A bigger concern is how are you going to normailize the data, and how are you going to do cross validation to get the proper values for svm_params?

Also, since svmPredict() reloads everything for every test case, it will be very inefficient.

You would be probably be better off using the libsvm command line tools until you know whether it is going to work. It would be trivial to dump the mats output from createTrainDataUsingBow() data in libsvm format.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM