【问题标题】:image classification using SVM and BOW?使用 SVM 和 BOW 进行图像分类?
【发布时间】:2014-03-22 22:09:46
【问题描述】:

我对 openCV 不太熟悉。我有一些图像,我想检查它们是否包含我正在寻找的标志。所以,我想使用我有一些代码的 SVM 技术。我已经理解了代码的大部分部分,但我不知道如何实现此代码。该代码具有三个功能,即createTrainDataUsingBow() 第二个是 int trainSVMint svmPredict

问题:我知道首先我必须训练 SVM,然后使用 predict()。但是,我不明白他们通话期间要传递的参数。我的意思是,如果我创建一个main(),那么我应该使用什么参数调用int trainSVM

整个代码如下:

1. 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. 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. 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;
}

【问题讨论】:

    标签: c++ opencv


    【解决方案1】:

    我应该将哪些参数称为 int trainSVM。

    trainSVM() 采用两个 char* 向量,它们分别是正样本和负样本的图像文件名称列表。 最好制作一个包含正图像文件名列表的文件,对于负图像文件名也一样,然后将其读入。

    顺便说一句,这行有语法错误:

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

    一个更大的问题是您将如何规范化数据,以及您将如何进行交叉验证以获得 svm_params 的正确值?

    此外,由于svmPredict() 会为每个测试用例重新加载所有内容,因此效率会非常低。

    在您知道它是否可以工作之前,您最好还是使用libsvm 命令行工具。将 createTrainDataUsingBow() 数据中的 mats 输出转储为 libsvm 格式将是微不足道的。

    【讨论】:

    • 谢谢,我理解了代码及其参数,但我在创建 svmPredict() 时仍然面临问题。为此,我将发布一个新问题。
    猜你喜欢
    • 2016-09-13
    • 2014-05-12
    • 2016-08-09
    • 2016-05-15
    • 2016-01-21
    • 2012-04-19
    • 2012-06-05
    • 2016-12-01
    • 2016-06-25
    相关资源
    最近更新 更多