OpenCV C ++的SVM返回相同类图像的相同置信度分数

时间:2015-05-11 10:09:34

标签: c++ opencv svm rank surf

我已经训练了20个班级的SVM,现在为了一个新的图像,我想首先将其归类为20个训练班级中的一个,然后根据其分类显示置信度分数。

问题:当我测试了1级的一些图像时,他们都返回了相同的置信度。我知道每张图片都应根据其分类得到不同的分数。所以我知道我的代码存在问题。

我甚至更改了" opencv"上的实例变量float * decision_function。从受保护到公共的框架并重建它,但问题仍未解决。

我想计算正确的分数,因为我希望稍后根据置信度分数对与我的查询图像最匹配的图像进行排名。

请让我知道为什么我在同一个班级中的每个图片获得相同的置信度分数,并且在我的代码中我犯了错误。

Ptr<DescriptorMatcher> matcher = DescriptorMatcher::create("FlannBased"); 
Ptr<DescriptorExtractor> extractor = new SurfDescriptorExtractor();
SurfFeatureDetector detector(500);// hemessian threshold

int dictionarySize = 100;  //number of clusters=100
TermCriteria tc(CV_TERMCRIT_ITER, 10, 0.001);
int retries = 1;
int flags = KMEANS_PP_CENTERS;
BOWKMeansTrainer bowTrainer(dictionarySize, tc, retries, flags);
BOWImgDescriptorExtractor bowDE(extractor, matcher);

int main( int argc, char** argv )
{
    int i,j;
    Mat dictionary; // creating a dictionary
    FileStorage fs("dictionary_new.yml", FileStorage::READ);
    fs ["vocabulary"]>> dictionary;
    fs.release();

    bowDE.setVocabulary(dictionary);
    Mat labels(0, 1, CV_32FC1);  //to store labels of images
    Mat trainingData(0, dictionarySize, CV_32FC1);
    int k=0;

    CvSVMParams params;
    params.kernel_type=CvSVM::RBF;
    params.svm_type=CvSVM::C_SVC;
    params.gamma=0.50625000000000009;
    params.C=312.50000000000000;
    params.term_crit=cvTermCriteria(CV_TERMCRIT_ITER,100,0.000001);
    CvSVM svm;

    svm.load("svm_new.yml");
    cout<<"Processing evaluation data..."<<endl;
    string tags[] = {"none","Plane","Bike","Face","Car","Bag","binocular","Gloves","Bread_Maker","Revolver","Ring","Guitar","Elephant","boat","French_horn","Gorilla","Headphone","Flower","Penguin","Tiger","Laptop"};
    Mat evalData(0, dictionarySize, CV_32FC1);
    k=0;
    vector<KeyPoint> keypoint2;
    Mat bowDescriptor2;
    Mat img2; //to load an image

    img2 = imread("3 (14).jpg");
    detector.detect(img2, keypoint2);
    bowDE.compute(img2, keypoint2, bowDescriptor2);
    evalData.push_back(bowDescriptor2);
    float response = svm.predict(bowDescriptor2, true);
    float confidence=0;
    int f_to_i=(int)response;
    confidence=1.0/(1.0+exp(-response));
    cout<<"\n\nIt's a "<<tags[f_to_i]<<" and its confidence: "<<confidence;

    _getch();
    return 0; 
}

计算得分:

1 (1).jpg,Plane,0.731059
1 (2).jpg,Plane,0.731059
1 (3).jpg,Plane,0.731059
1 (4).jpg,Plane,0.731059
1 (5).jpg,Plane,0.731059
1 (6).jpg,Plane,0.731059
1 (7).jpg,Plane,0.731059
1 (8).jpg,Plane,0.731059
1 (9).jpg,Plane,0.731059
1 (10).jpg,Plane,0.731059
1 (11).jpg,Plane,0.731059
1 (12).jpg,Plane,0.731059
1 (13).jpg,Plane,0.731059
1 (14).jpg,Plane,0.731059
1 (15).jpg,Plane,0.731059
1 (16).jpg,Plane,0.731059
1 (17).jpg,Plane,0.731059
1 (18).jpg,Plane,0.731059
1 (19).jpg,Plane,0.731059
1 (20).jpg,Plane,0.731059

1 个答案:

答案 0 :(得分:2)

我遇到了类似的问题。问题是当你有超过2个类时,你无法使用svm.predict(bowDescriptor2,true)获得响应。如果问题是多类OpenCv SVM将只返回类标签号。这就解释了为什么你有相同的价值观。

查看文档:{​​{3}}

“returnDFVal - 指定返回值的类型。如果为true且问题是2级分类,则该方法返回与边距签名距离的决策函数值,否则函数返回类标签(分类)或估计的函数值(回归)。“

一种可能的解决方案是修改 float CvSVM :: predict(const float * row_sample,int row_len,bool returnDFVal)方法。在那里,您可以进行更改以获取每个类的decisionFunctionValues。

查看部分代码: ...

for (i = 0; i < class_count; i++)
{
    for (j = i + 1; j < class_count; j++, df++)
    {
        sum = -df->rho;
        int sv_count = df->sv_count;
        for (k = 0; k < sv_count; k++)
            sum += df->alpha[k] * buffer[df->sv_index[k]];

        vote[sum > 0 ? i : j]++;
    }
}

for (i = 1, k = 0; i < class_count; i++)
{
    if (vote[i] > vote[k])
        k = i;
}
result = returnDFVal && class_count == 2 ? (float)sum : (float)(class_labels->data.i[k]);