OpenCV:如何使用自定义SVM与HOGDescriptor :: detectMultiScale()?

5

我使用自己的正负样本,基于HOG特征训练了一个CvSVM模型:

CvSVMParams params;
params.svm_type    = CvSVM::C_SVC;
params.kernel_type = CvSVM::RBF;

CvSVM svm;
svm.train_auto(descriptors, labels, cv::Mat(), cv::Mat(), params,
               SVM_CROSS_VALIDATION_K);

我可以很好地使用分类图像:

cv::HOGDescriptor hog;
hog.winSize = cv::Size(HOG_PARAMS.width(), HOG_PARAMS.height());

//compute the HOG features
hog.compute(image, ders,
            cv::Size(HOG_PARAMS.stride(),HOG_PARAMS.stride()),
            cv::Size(0,0), locs);

//convert the feature to a Mat
cv::Mat desc_mat;
desc_mat.create(ders.size(), 1, CV_32FC1);
for(unsigned int i = 0; i < ders.size(); i++)
  desc_mat.at<float>(i, 0) = ders[i];

float response = svm.predict(desc_mat);

现在我想使用HOGDescriptor::detectMultiScale()函数在图像中检测感兴趣的物体。为了将CvSVM转换为HOGDescriptor所需的原始形式,我使用了https://dev59.com/bm_Xa4cB1Zd3GeqP1n52#17118561建议的方法:

detector_svm.h:

#ifndef DETECTOR_SVM_H
#define DETECTOR_SVM_H

#include <opencv2/core/core.hpp>
#include <opencv2/ml/ml.hpp>

class Detector_svm : public CvSVM
{
  public:
  std::vector<float> get_primal_form() const;
};  

#endif //DETECTOR_SVM_H

detector_svm.cpp:

#include "detector_svm.h"

std::vector<float> Detector_svm::get_primal_form() const
{
  std::vector<float> support_vector;

  int sv_count = get_support_vector_count();

  const CvSVMDecisionFunc* df = decision_func;
  const double* alphas = df[0].alpha;
  double rho = df[0].rho;
  int var_count = get_var_count();

  support_vector.resize(var_count, 0);

  for (unsigned int r = 0; r < (unsigned)sv_count; r++) 
  {
    float myalpha = alphas[r];
    const float* v = get_support_vector(r);
    for (int j = 0; j < var_count; j++,v++) 
    {
      support_vector[j] += (-myalpha) * (*v);
    }
  }

  support_vector.push_back(rho);

  return support_vector;
}

然而,当我尝试设置SVM检测器时。
HOGDescriptor hog;
hog.setSVMDetector(primal_svm); //primal_svm is a std::vector<float>

我遇到了失败的断言:

OpenCV Error: Assertion failed (checkDetectorSize()) in setSVMDetector, file /home/username/libs/OpenCV-2.3.1/modules/objdetect/src/hog.cpp, line 89
terminate called after throwing an instance of 'cv::Exception'
  what():  /home/username/libs/OpenCV-2.3.1/modules/objdetect/src/hog.cpp:89: error: (-215) checkDetectorSize() in function setSVMDetector

我已经尝试使用OpenCV 2.3.1和2.4.7运行这个程序,但结果是一样的。我做错了什么?

你解决过这个问题吗?我也遇到了同样的问题。 - PhilBot
我还没有解决它。我通过编写自己的多尺度检测器来绕过它。 - StaringFrog
5个回答

2

我曾经也遇到过同样的问题。后来我发现是因为我给HogDescriptor函数传递了错误的winSize参数。winSize应该与你的训练图像的尺寸匹配。在我的情况下,我使用了32x64的图像进行训练,所以我需要使用winSize=(32x64)。我的设置检测器的代码如下。

 vector<float> primal;
 svm.getSupportVector(primal);
 cv::HOGDescriptor hog(cv::Size(32, 64), cv::Size(8, 8), cv::Size(4, 4), cv::Size(4, 4), 9);
 hog.setSVMDetector(primal);

1
您训练的向量大小可能太小了。您需要确保在训练时窗口的大小与描述符大小匹配。 win_size=Size(64, 128) block_size=Size(16, 16) block_stride=Size(8, 8) cell_size=Size(8, 8) nbins=9

0

如果你的primal_svm.size()hog.getDescriptorSize()不同,就会抛出该错误。

我在你的代码中没有立即发现任何问题,但显然缺少一些样板文件。


0

您需要像这样初始化您的HOG: hog(cv::Size(64, 64), cv::Size(16, 16), cv::Size(8, 8), cv::Size(8, 8), 9),并确保参数值与您的匹配。


0

我不再能够访问原始代码。

为了解决这个问题,我编写了自己的多尺度检测器,这比获取原始SVM形式更少工作。

我现在对于遇到类似问题的人的建议是尝试升级到OpenCV 3.x。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接