SVM预测OpenCV:我如何提取相同数量的功能

时间:2017-10-25 15:25:37

标签: c++ opencv machine-learning svm

我正在使用OpenCV和SVM制作分类器来预测面部表情。我对测试dadaset进行分类没有问题,但是当我尝试预测新图像时,我得到了这个:

OpenCV错误:断言失败(samples.cols == var_count&& samples.type()== CV_32F)在cv :: ml :: SVMImpl :: predict

错误非常清楚,我有不同数量的列,但属性相同。 我不知道如何实现这一点,因为我有一个维度为1xnumber_of_features的矩阵,但numbers_of_features与经过训练和测试的样本不同。如何从其他图像中提取相同数量的要素?我错过了什么吗?

为了训练分类器我做了:

  • 检测面部并节省投资回报率;
  • 筛选提取功能;
  • kmeans聚集他们;
  • 为每张图片获取相同数量的功能;
  • pca to reduce;
  • 在火车上训练爸爸;
  • 预测测试爸爸;

在新图像上我做了同样的事情。

我尝试将新图像调整为相同大小,但没有任何相同的错误(以及不同数量的列,也就是特征)。矢量属于同一类型(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));
}

0 个答案:

没有答案