Opencv SVM为不同的图像输入预测相同的标签?

时间:2017-04-19 19:40:11

标签: c++ opencv svm

此网站中有许多类似的问题,例如thisthis以及有关如何优化SVM参数以获得准确结果的许多资源,但没有任何解决方案可以解决我的问题。我正在使用Opencv SVM我有100个训练图像,有三个类(猫,狗和人),我还有10个来自训练图像的测试图像。

我的代码是

 //Read images, detect the keypoints and compute descriptor.
 for(int i=0; i<99; i++)
    {

        sprintf(filePathName,"C:\\Users\\what\\Documents\\images\\%i.jpg",i+1);
        mat=cv::imread(filePathName);
        siftFeatureDetector.detect(mat,keypoint);
        siftDescriptorExtractor.compute(mat,keypoint,descriptor);
   //add the descriptor to unclustered descriptor to cluster them using Bow.
        unclusteredDescriptors.push_back(descriptor);

    }
int dictionarySize=2000;
int retries=1;
cv::TermCriteria tc(cv::TermCriteria::COUNT,100000,0.001);
int flags=KMEANS_PP_CENTERS;
cv::BOWKMeansTrainer bowTrainer(dictionarySize,tc,retries,flags);
cv::Mat dictionary=bowTrainer.cluster(unclusteredDescriptors);

//Label the images
vector<string> imageFilenames;
vector<string> labels;
for(int i=0; i<99; i++)
{
    sprintf(filename,"C:\\Users\\what\\Documents\\images\\%i.jpg",i+1);
    imageFilenames.push_back(filename);
    if(i>=0 && i<=46)
        labels.push_back("Cat");
    else if(i>46&&i<=92)
        labels.push_back("Dog");
    else if(i>92&&i<=99)
        labels.push_back("Human");
    else
        cout<<"Error in labeling the  images"<<endl;
}
cv::Ptr<cv::FeatureDetector> siftFeatureDetector(new cv::SiftFeatureDetector(1000));
cv::Ptr<cv::DescriptorExtractor> siftDescriptorExtractor(new cv::SiftDescriptorExtractor);
cv::Ptr<cv::DescriptorMatcher> flannDescriptorMatcher(new cv::FlannBasedMatcher);
cv::BOWImgDescriptorExtractor bowImgDescriptorExtractor(siftDescriptorExtractor,flannDescriptorMatcher);
bowImgDescriptorExtractor.setVocabulary(dictionary);

//compute the image descriptor using the BOWImgDescriptorExtractor.  
string filename;
cv::Mat image;
vector<cv::KeyPoint> keypoint;
cv::Mat descriptor;
string label;
map<string,cv::Mat> mapedImage;
 for(int i=0; i<filenames.size(); i++)

{
    filename=imageFilenames[i];
    label=labels[i];
    image=cv::imread(filename);
    siftFeatureDetector->detect(image,keypoint);
    bowImgDescriptorExtractor.compute(image,keypoint,descriptor);
    if(mapedImage.count(label)==0)
    {
        mapedImage[label].create(0,descriptor.cols,descriptor.type());
     }

    mapedImage[label].push_back(descriptor);

}

//Train the data using SVM one-vs-one multi-class classifier.
vector<string> trainClassName;
cv::SVMParams params;
    params.kernel_type = CvSVM::RBF; //CvSVM::RBF, CvSVM::LINEAR ...
    params.svm_type=SVM::C_SVC;
    params.term_crit = cvTermCriteria(CV_TERMCRIT_ITER+CV_TERMCRIT_EPS,1000000,0.000001);
for(map<string,cv::Mat>::iterator it =mapedImage.begin(); it!=mapedImage.end(); it++)
{

    trainClassName.push_back(it->first);
}
//Train the Cat vs Dog.
 cv::Mat svmTrainData1;
cv::Mat svmLabels1;//
string stringLabel1;
//positive sample.
 stringLabel1=trainClassName[0];
svmTrainData1.push_back(mapedImage[stringLabel1]);
cv::Mat labelone1=cv::Mat::ones(mapedImage[stringLabel1].rows,1,CV_32SC1);
svmLabels1.push_back(labelone1);
//negative sample.
stringLabel1=trainClassName[1];
svmTrainData1.push_back(mapedImage[stringLabel1]);
cv::Mat labelzero1=cv::Mat::zeros(mapedImage[stringLabel1].rows,1,CV_32SC1);
svmLabels1.push_back(labelzero1);
cv::SVM svm1;
    bool trainSvm1=svm1.train_auto(svmTrainData1,svmLabels1,cv::Mat(),cv::Mat(),params,10,SVM::get_default_grid(SVM::C),SVM::get_default_grid(SVM::GAMMA),SVM::get_default_grid(SVM::P),SVM::get_default_grid(SVM::NU),
                     SVM::get_default_grid(SVM::COEF),SVM::get_default_grid(SVM::DEGREE),false); 
                 SVM::get_default_grid(SVM::COEF),SVM::get_default_grid(SVM::DEGREE),false); 
//i have trained the Cat, Human and Human, Dog the same as above. 
 //Test stage.
cv::SVM svmcatordog;
cv::SVM svmcatorhuman;
cv::SVM svmdogorhuman;
svmcatordog.load("C:\\Users\\what\\Documents\\svmcatordog.yml");
svmcatorhuman.load("C:\\Users\\what\\Documents\\svmcatorhuman.yml");
svmdogorhuman.load("C:\\Users\\what\\Documents\\svmdogorhuman.yml");
for(int i=0;i<10;i++)
{   sprintf(fileName,"C:\\Users\\what\\Documents\\images\\testImage\\%i.jpg",i+1);
images=cv::imread(fileName);
vector<cv::KeyPoint> keypoint;
cv::Mat testImageDescriptor;
siftFeatureDetector->detect(images,keypoint);
bowImgDescriptorExtractor.compute(images,keypoint,testImageDescriptor);
int catCount=0;
int dogCount=0;
int humanCount=0;
int result1=svmcatordog.predict(testImageDescriptor);
if(result1==1)
    catCount++;
if(result1==0)
    dogCount++;
int result2=svmcatorhuman.predict(testImageDescriptor); 
if(result2==1)
    catCount++;
if(result2==0)
    humanCount++;
int result3=svmdogorhuman.predict(testImageDescriptor); 
if(result3==1)
    dogCount++;
if(result3==0)
    humanCount++;
if(catCount>dogCount&&catCount>>humanCount)
        cout<<"Image at "<<i+1<<" have cat"<<endl;
    else if(dogCount>catCount&&dogCount>humanCount)
        cout<<"Image at "<<i+1<<" have dog"<<endl;
    else if(humanCount>catCount&&humanCount>dogCount)
        cout<<"Image at "<<i+1<<" have human"<<endl;
    else if(catCount==dogCount&&catCount==humanCount)
         cout<<"Ambiguous catCount,dogCount and humanCount   are the same"<<endl;
    else if(catCount==dogCount)
        cout<<"Ambiguous catCount and dogCount are the same"<<endl;
    else if(catCount==humanCount)
        cout<<"Ambiguous catCount and humanCount are the same"<<endl;
    else if(dogCount==humanCount)
        cout<<"Ambiguous dogCount and humanCount are the same"<<endl;
    else
        cout<<"Error in the counting results"<<endl; 

}

当我预测训练图像时,结果是相同的标签。它是“Image have a cat”或“Ambiguous catCount,dogCount和humanCount是相同的”。基于this问题答案,我开始在train_auto方法中将C和gamma的默认值更改为C和gamma的值,我将C的值从0.1更改为1000,将gamma的值从1e-0008更改为到1000仍然结果不正确。任何人都可以帮助我停止为不同的输入预测相同的标签吗? 对不起,很长的帖子!

0 个答案:

没有答案