我正在使用OpenCV和SVM制作分类器来预测面部表情。我对测试dadaset进行分类没有问题,但是当我尝试预测新图像时,我得到了这个:
OpenCV错误:断言失败(samples.cols == var_count&& samples.type()== CV_32F)在cv :: ml :: SVMImpl :: predict
错误非常清楚,我有不同数量的列,但属性相同。 我不知道如何实现这一点,因为我有一个维度为1xnumber_of_features的矩阵,但numbers_of_features与经过训练和测试的样本不同。如何从其他图像中提取相同数量的要素?我错过了什么吗?
为了训练分类器我做了:
在新图像上我做了同样的事情。
我尝试将新图像调整为相同大小,但没有任何相同的错误(以及不同数量的列,也就是特征)。矢量属于同一类型(CF_32F)。
[编辑1] 让我们尝试更具体一点。 在成功训练了我的分类器之后,我以这种方式保存了SVM模型
svmClassifier->save(baseDatabasePath);
然后我在需要以这种方式进行实时预测时加载它
cv::Ptr<cv::ml::SVM> svmClassifier;
svmClassifier = cv::ml::StatModel::load<ml::SVM>(path);
然后循环,
while (true)
{
getOneImage();
cv::Mat feature = extractFeaturesFromSingleImage();
float labelPredicted = svmClassifier->predict(feature);
cout << "Label predicted is: " << labelPredicted << endl;
}
但是predict
会返回错误。例如,要素尺寸为1x66。如您所见,我需要140个功能
<?xml version="1.0"?>
<opencv_storage>
<opencv_ml_svm>
<format>3</format>
<svmType>C_SVC</svmType>
<kernel>
<type>RBF</type>
<gamma>5.0625000000000009e-01</gamma></kernel>
<C>1.2500000000000000e+01</C>
<term_criteria><epsilon>1.1920928955078125e-07</epsilon>
<iterations>1000</iterations></term_criteria>
<var_count>140</var_count>
<class_count>7</class_count>
<class_labels type_id="opencv-matrix">
<rows>7</rows>
<cols>1</cols>
<dt>i</dt>
<data>
0 1 2 3 4 5 6</data></class_labels>
<sv_total>172</sv_total>
我不知道如何实现140个功能,当SIFT,FAST或SURF只给我60个功能时。我错过了什么?
编辑2 :我将尝试更正式:如何将我的实时样本放在列车和测试数据集的相同维度上?
编辑3: 通过筛选提取特征并推动垫子矢量。
std::vector<cv::Mat> featuresVector;
for (int i = 0; i < numberImages; ++i)
{
cv::Mat face = cv::imread(facePath, CV_LOAD_IMAGE_GRAYSCALE);
cv::Mat featuresExtracted = runExtractFeature(face, featuresExtractionAlgorithm);
featuresVector.push_back(featuresExtracted);
}
获取从所有图像中提取的全部特征。
int numberFeatures = 0;
for (int i = 0; i < featuresVector.size(); ++i)
{
numberFeatures += featuresVector[i].rows;
}
准备垫子以群集功能(我尝试按照this示例)
cv::Mat featuresData = cv::Mat::zeros(numberFeatures, featuresVector[0].cols, CV_32FC1);
int currentIndex = 0;
for (int i = 0; i < featuresVector.size(); ++i)
{
featuresVector[i].copyTo(featuresData.rowRange(currentIndex, currentIndex + featuresVector[i].rows));
currentIndex += featuresVector[i].rows;
}
执行群集(我不知道这个参数如何适应我的情况,我认为我现在可以做好)
cv::Mat labels;
cv::Mat centers;
int binSize = 1000;
kmeans(featuresData, binSize, labels, cv::TermCriteria(cv::TermCriteria::COUNT + cv::TermCriteria::EPS, 100, 1.0), 3, KMEANS_PP_CENTERS, centers);
准备垫子以进行鞠躬。
cv::Mat featuresDataHist = cv::Mat::zeros(numberImages, binSize, CV_32FC1);
for (int i = 0; i < numberImages; ++i)
{
cv::Mat feature = cv::Mat::zeros(1, binSize, CV_32FC1);
int numberImageFeatures = featuresVector[i].rows;
for (int j = 0; j < numberImageFeatures; ++j)
{
int bin = labels.at<int>(currentIndex + j);
feature.at<float>(0, bin) += 1;
}
cv::normalize(feature, feature);
feature.copyTo(featuresDataHist.row(i));
currentIndex += featuresVector[i].rows;
}
PCA试图减少维度。
cv::PCA pca(featuresDataHist, cv::Mat(), CV_PCA_DATA_AS_ROW, 50/*0.90*/);
cv::Mat feature;
for (int i = 0; i < numberImages; ++i)
{
feature = pca.project(featuresDataHist.row(i));
}