此网站中有许多类似的问题,例如this,this以及有关如何优化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仍然结果不正确。任何人都可以帮助我停止为不同的输入预测相同的标签吗? 对不起,很长的帖子!