我的目标是使用带有HOG特征的SVM模型来对交通中的轿车和SUV进行分类。
我使用了不同的核函数(RBF、LINEAR、POLY),它们各自给出了不同的结果,但无论参数如何改变,结果都是相同的。例如,当我使用POLY核函数且度数大于或等于0.65时,它会将所有内容分类为SUV;如果度数小于0.65,则所有测试图像都会被分类为轿车。
使用LINEAR核函数时,唯一改变的参数是C。不管C的参数是什么,我总是得到8/10的图像被分类为轿车,另外2个被分类为SUV。
目前我只有大约70张训练图像和10张测试图像,我还没有找到一个好的从后方和上方拍摄的车辆数据集,就像我将要使用的桥梁上的视角一样。问题可能是由于这个小数据集,还是参数问题,或者其他原因?此外,我注意到我的支持向量通常非常高,比如70张训练图像中有58张,这可能是数据集的问题吗?有没有办法让我以某种方式可视化训练点——在SVM的例子中,他们总是有一个漂亮的二维点图,并在其中画一条线,但有没有办法用图像来绘制这些点,这样我就可以看看我的数据是否线性可分,并相应地进行调整?我的HOG参数对于150×200的汽车图像是否准确?
另外需要注意的是,当我使用与训练图像相同的测试图像时,SVM模型预测得非常完美,但显然这是作弊。
下图显示了结果,以及测试图像的一个示例
这是我的代码,我没有包括大部分代码,因为我不确定代码是否是问题所在。首先,我提取正图像的HOG特征,然后将它们加载到训练Mat中,然后对负图像做同样的事情,就像我对包含的测试部分所做的那样。
//Set SVM Parameters (not sure about these values, but just wanna see something)Ptr<SVM> svm = SVM::create();svm->setType(SVM::C_SVC);svm->setKernel(SVM::POLY);svm->setC(50);svm->setGamma(100);svm->setDegree(.65);//svm->setTermCriteria(TermCriteria(TermCriteria::MAX_ITER, 100, 1e-6));cout << "Parameters Set..." << endl;svm->train(HOGFeat_train, ROW_SAMPLE, labels_mat);Mat SV = svm->getSupportVectors();Mat USV = svm->getUncompressedSupportVectors();cout << "Support Vectors: " << SV.rows << endl;cout << "Uncompressed Support Vectors: " << USV.rows << endl;cout << "Training Successful" << endl;waitKey(0);//TESTING PORTIONcout << "Begin Testing..." << endl;int num_test_images = 10;Mat HOGFeat_test(1, derSize, CV_32FC1); //Creates a 1 x descriptorSize Mat to house the HoG features from the test imagefor (int file_count = 1; file_count < (num_test_images + 1); file_count++){ test << nameTest << file_count << type; //'Test_1.jpg' ... 'Test_2.jpg' ... etc ... string filenameTest = test.str(); test.str(""); Mat test_image = imread(filenameTest, 0); //Read the file folder HOGDescriptor hog_test;// (Size(64, 64), Size(32, 32), Size(16, 16), Size(32, 32), 9, 1, -1, 0, .2, 1, 64, false); vector<float> descriptors_test; vector<Point> locations_test; hog_test.compute(test_image, descriptors_test, Size(64, 64), Size(0, 0), locations_test); for (int i = 0; i < descriptors_test.size(); i++) HOGFeat_test.at<float>(0, i) = descriptors_test.at(i); namedWindow("Test Image", CV_WINDOW_NORMAL); imshow("Test Image", test_image); //Should return a 1 if its an SUV, or a -1 if its a sedan float result = svm->predict(HOGFeat_test); if (result <= 0) cout << "Sedan" << endl; else cout << "SUV" << endl; cout << "Result: " << result << endl; waitKey(0);}
回答:
解决这个问题有两个方法:
1) 我获得了一个更大的车辆数据集。我使用了大约400张SUV图像和400张轿车图像进行训练部分,然后另外50张图像用于测试部分。
2) 在:Mat HOGFeat_test(1, derSize, CV_32FC1),我的derSize参数大约大了一个数量级。实际大小是15120,但我让Mat有113400列。因此,我只填充了大约10%的测试Mat中有用的特征数据,所以SVM很难区分SUV和轿车。
现在它在线性和多项式核函数(C = 10)下都运行得很好,我的准确率比预期的还要好,达到了96%。