我正在尝试训练我自己的探测器以便与OpenCV :: HOGDescriptor一起使用,但我无法使现有的HOGDescriptor与我新训练的SVM一起工作。
我已计算出正面和负面训练图像的HOG功能,标记它们并使用CvSVM训练SVM。我使用的参数是:
CvSVMParams params;
params.svm_type =CvSVM::EPS_SVR;
params.kernel_type = CvSVM::LINEAR;
params.C = 0.01;
params.p = 0.5;
然后我计算支持向量的原始形式,这样我只得到一个向量而不是多个向量,并使用HOGDescriptor.setSVMDetector(向量)设置计算的支持向量;
当我使用CvSVM.predict()时,我能够使用SVM正确地对对象进行分类,但是HOGDescriptor.detect()或detectMultiScale()总是返回许多正匹配,并且不能给出准确的预测。
CvSVM.predict()使用原始支持向量进行分类,因此我计算原始形式的方式可能有问题。
有没有人训练过他们自己的探测器谁可以指出我正确的方向?
答案 0 :(得分:5)
我编写了一个CvSVM子类,在训练线性svm后提取原始形式。阳性样品标记为1,阴性样品标记为-1。奇怪的是,我必须在alphas前加上负号,并保持rho的符号不变,以便从HogDescriptor中获得正确的结果。
LinearSVM.h
#ifndef LINEAR_SVM_H_
#define LINEAR_SVM_H_
#include <opencv2/core/core.hpp>
#include <opencv2/ml/ml.hpp>
class LinearSVM: public CvSVM {
public:
void getSupportVector(std::vector<float>& support_vector) const;
};
#endif /* LINEAR_SVM_H_ */
LinearSVM.cc
#include "linear_svm.h"
void LinearSVM::getSupportVector(std::vector<float>& support_vector) const {
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);
}
答案 1 :(得分:4)
我正在努力解决同样的问题。搜索我发现的论坛,使用CvSVM无法训练探测器(我不知道原因)。我使用LIBSVM来训练探测器。以下是为HOGDescriptor.setSVMDetector(w)提取检测器的代码:有关数据详细信息,请参阅LIBSVM文档/标题。我用C ++完成了所有的训练,将LIBSVM训练数据从CV填充到LIBSVM;下面的代码提取了cv :: HOGDescriptor所需的检测器向量。 w参数为std::vector<float> w
const double * const *sv_coef = model.sv_coef;
const svm_node * const *SV = model.SV;
int l = model.l;
model.label;
const svm_node* p_tmp = SV[0];
int len = 0;
while( p_tmp->index != -1 )
{
len++;
p_tmp++;
}
w.resize( len+1 );
for( int i=0; i<l; i++)
{
double svcoef = sv_coef[0][i];
const svm_node* p = SV[i];
while( p->index != -1 )
{
w[p->index-1] += float(svcoef * p->value);
p++;
}
}
w[len] = float(-model.rho[0]);
希望这会有所帮助......
答案 2 :(得分:0)
根据我在Dalal关于HOG探测器的论文中所读到的,他建议为了消除误报,我们需要重新训练我们的模型。通过应用初步模型(您的模型产生大量误报)完成再训练,然后检测所有负样本图像中的对象。所有返回的矩形肯定会出现误报。
然后,将所有这些误报添加到您的负样本图像(负数据集),再次进行训练。如文中所建议的,由此产生的模型将返回更少的误报。
不幸的是,虽然我试过了(重新训练),但是得到的模型只是没有识别任何东西,即使在正面图像样本上也是如此。但我认为这值得一试,因为这是发明人关于HOG探测器的文章中提出的建议