从CvSVM训练文件获取原始形式

时间:2014-08-06 11:18:15

标签: opencv svm

我正在尝试基于HOG功能训练我自己的探测器,并且我使用opencv的CvSVM实用程序训练了一个探测器。现在在HOGDescriptor.SetSVM(myDetector)中使用此检测器,我需要以行向量(原始)形式获取训练的检测器以进行提供。为此我使用this代码。我的实现如下:

vector<float>primal;

void LinearSVM::getSupportVector(std::vector<float>& support_vector)  {

    CvSVM svm;
    svm.load("Classifier.xml");
    cin.get();
    int sv_count = svm.get_support_vector_count();
    const CvSVMDecisionFunc* df = decision_func;
    const double* alphas = df[0].alpha;
    double rho = df[0].rho;
    int var_count = svm.get_var_count();
    support_vector.resize(var_count, 0);
    for (unsigned int r = 0; r < (unsigned)sv_count; r++) {
      float myalpha = alphas[r];
      const float* v = svm.get_support_vector(r);
      for (int j = 0; j < var_count; j++,v++) {
        support_vector[j] += (-myalpha) * (*v);
      }
    }
    support_vector.push_back(rho);
}

int main()
{

    LinearSVM s;
    s.getSupportVector(primal);

    return 0;
}

当我使用内置的CvSVM时,它显示SV为3因为我在保存的文件中只有3个SV,但由于decision_func处于保护模式,因此我无法访问它。这就是为什么我试图使用那个包装但仍然没用的原因。也许你们可以在这里帮助我......非常感谢!

2 个答案:

答案 0 :(得分:0)

你好再次:)请扩展cvsm类而不是封装它,因为你需要访问受保护的成员。

//header
class mySVM : public CvSVM
{

public:
    vector<float>
    getWeightVector(const int descriptorSize);
};

//cpp
vector<float>
mySVM::getWeightVector(const int descriptorSize)
{
    vector<float> svmWeightsVec(descriptorSize+1);
    int numSupportVectors = get_support_vector_count();

    //this is protected, but can access due to inheritance rules 
    const CvSVMDecisionFunc *dec = CvSVM::decision_func;

    const float *supportVector;
    float* svmWeight = &svmWeightsVec[0];

    for (int i = 0; i < numSupportVectors; ++i)
    {
        float alpha = *(dec[0].alpha + i);
        supportVector = get_support_vector(i);
        for(int j=0;j<descriptorSize;j++)
        {
            *(svmWeight + j) += alpha * *(supportVector+j);
        }
    }
    *(svmWeight + descriptorSize) = - dec[0].rho;

    return svmWeightsVec;
}

类似的东西。

币: Obtaining weights in CvSVM, the SVM implementation of OpenCV

答案 1 :(得分:0)

用测试工具回答。我提出了新的答案,因为它会给原来的答案增加一些混乱,可能会让它有点混乱。

//dummy features
std:: vector<float> 
dummyDerReaderForOneDer(const vector<float> &pattern)
{
    int i = std::rand() % pattern.size();
    int j = std::rand() % pattern.size();
    vector<float> patternPulNoise(pattern);
    std::random_shuffle(patternPulNoise.begin()+std::min(i,j),patternPulNoise.begin()+std::max(i,j));
    return patternPulNoise;
};

//extend CvSVM to get access to weights
class mySVM : public CvSVM
{
public:
    vector<float>
    getWeightVector(const int descriptorSize);
};

//get the weights
vector<float>
mySVM::getWeightVector(const int descriptorSize)
{
    vector<float> svmWeightsVec(descriptorSize+1);
    int numSupportVectors = get_support_vector_count();

    //this is protected, but can access due to inheritance rules 
    const CvSVMDecisionFunc *dec = CvSVM::decision_func;

    const float *supportVector;
    float* svmWeight = &svmWeightsVec[0];

    for (int i = 0; i < numSupportVectors; ++i)
    {
        float alpha = *(dec[0].alpha + i);
        supportVector = get_support_vector(i);
        for(int j=0;j<descriptorSize;j++)
        {
            *(svmWeight + j) += alpha * *(supportVector+j);
        }
    }
    *(svmWeight + descriptorSize) = - dec[0].rho;

    return svmWeightsVec;
}


// main harness entry point for detector test
int main (int argc, const char * argv[])
{


    //dummy variables for example
    int posFiles = 10;
    int negFiles = 10;
    int dims = 1000;
    int randomFactor = 4;

    //setup some dummy data
    vector<float> dummyPosPattern;
    dummyPosPattern.assign(int(dims/randomFactor),1.f);
    dummyPosPattern.resize(dims );
    random_shuffle(dummyPosPattern.begin(),dummyPosPattern.end());

    vector<float> dummyNegPattern;
    dummyNegPattern.assign(int(dims/randomFactor),1.f);
    dummyNegPattern.resize(dims );
    random_shuffle(dummyNegPattern.begin(),dummyNegPattern.end());

    // the labels and lables mat
    float posLabel = 1.f;
    float negLabel = 2.f;
    cv::Mat cSvmLabels;

    //the data mat
    cv::Mat cSvmTrainingData;

    //dummy linear svm parmas
    SVMParams cSvmParams;
    cSvmParams.svm_type = cv::SVM::C_SVC;
    cSvmParams.C = 0.0100;
    cSvmParams.kernel_type = cv::SVM::LINEAR;
    cSvmParams.term_crit =  cv::TermCriteria(CV_TERMCRIT_ITER+CV_TERMCRIT_EPS, 1000000, FLT_EPSILON);




    cout << "creating training data. please wait" << endl;
    int i;
    for(i=0;i<posFiles;i++)
    {
        //your feature for one box from file
        vector<float> d = dummyDerReaderForOneDer(dummyPosPattern);

        //push back a new mat made from the vectors data, with copy  data flag on
        //this shows the format of the mat for a single example, (1 (row) X dims(col) ), as  training mat has each **row** as an example;
        //the push_back works like vector add adds each example to the bottom of the matrix
        cSvmTrainingData.push_back(cv::Mat(1,dims,CV_32FC1,d.data(),true));

        //push back a pos label to the labels mat
        cSvmLabels.push_back(posLabel);
    }

    //do same with neg files;
    for(i=0;i<negFiles;i++)
    {
        float a =  rand(); 
        vector<float> d = dummyDerReaderForOneDer(dummyNegPattern);
        cSvmTrainingData.push_back(cv::Mat(1,dims,CV_32FC1,d.data(),true));
        cSvmLabels.push_back(negLabel);
    }

    //have a look
    cv::Mat viz;
    cSvmTrainingData.convertTo(viz,CV_8UC3);
    viz = viz*255;
    cv::imshow("svmData", viz);
    cv::waitKey(10);
    cout << "press any key to continue" << endl;
    getchar();

    viz.release();

    //create the svm;
    cout << "training, please wait" << endl;

    mySVM svm;
    svm.train(cSvmTrainingData,cSvmLabels,cv::Mat(),cv::Mat(),cSvmParams);


    cout << "get weights" << endl; 
    vector<float> svmWeights = svm.getWeightVector(dims);
    for(i=0; i<dims+1; i++)
    {
        cout << svmWeights[i] << ", ";
        if(i==dims)
        {
            cout << endl << "bias: "  << svmWeights[i]  << endl;
        }
    }

    cout << "press any key to continue" << endl;
    getchar();



    cout << "testing, please wait" << endl;
    //test the svm with a large amount of new unseen fake one at a time
    int totExamples = 10;
    int k;
    for(i=0;i<totExamples; i++)
    {
        cout << endl << endl;
        vector<float> dPos = dummyDerReaderForOneDer(dummyPosPattern);
        cv::Mat dMatPos(1,dims,CV_32FC1,dPos.data(),true);
        float predScoreFromDual = svm.predict(dMatPos,true);
        float predScoreBFromPrimal = svmWeights[dims];

        for( k = 0; k <= dims - 4; k += 4 )
                predScoreBFromPrimal += dPos[k]*svmWeights[k] + dPos[k+1]*svmWeights[k+1] +
                    dPos[k+2]*svmWeights[k+2] + dPos[k+3]*svmWeights[k+3];
            for( ; k < dims; k++ )
                predScoreBFromPrimal += dPos[k]*svmWeights[k];

         cout << "Dual Score:\t" << predScoreFromDual << "\tPrimal Score:\t" <<  predScoreBFromPrimal << endl; 

    }



    cout << "press any key to continue" << endl;
    getchar();
    return(0);
}