2013-03-11 4 views
5

Ich versuche, meine eigenen Detektor für den Einsatz mit OpenCV :: HOGDescriptor zu trainieren, aber ich habe Probleme mit dem bestehenden HOGDescriptor arbeiten mit meiner neu ausgebildeten SVM.Training benutzerdefinierte SVM mit HOGDescriptor in OpenCV

Ich habe HOG-Funktionen für positive und negative Trainingsbilder berechnet, beschriftet und die SVM mit CvSVM trainiert. Die Parameter, die ich verwendet habe, sind:

CvSVMParams params; 
    params.svm_type =CvSVM::EPS_SVR; 
    params.kernel_type = CvSVM::LINEAR; 
    params.C = 0.01; 
    params.p = 0.5; 

Dann I Urform der Stützvektoren berechnen, so dass ich nur statt vielen einen Vektor erhalten und stelle den berechneten Support-Vektor unter Verwendung von HOGDescriptor.setSVMDetector (Vektor);

This is Primal Form

Wenn ich CvSVM.predict() Ich bin in der Lage, richtig Objekte mit dem SVM zu klassifizieren, aber HOGDescriptor.detect() oder detectMultiScale() gibt immer viele positive Begegnungen und nicht genau geben Vorhersagen.

CvSVM.predict() verwendet die Original-Support-Vektoren für die Klassifizierung, so dass möglicherweise etwas falsch mit der Art bin, wie ich die ursprüngliche Form berechne.

Gibt es jemanden, der seinen eigenen Detektor trainiert hat, der mir in die richtige Richtung zeigen kann?

+0

Es scheint, als ob ein Fehler von libsvm vererbt wurde, in dem die Reihenfolge der Etiketten durcheinander geraten. Die Vorhersagefunktion kennt die Reihenfolge und schaut nach, welches Label welches ist und funktioniert somit gut. Ich habe das Problem gelöst, indem ich mein + ve-Label auf eine Zahl kleiner als meine -ve gesetzt habe, d. H. Pos = 1, neg = 2. Andernfalls müssen Sie möglicherweise Ihr Modell durch Multiplikation mit -1 invertieren. (Deshalb hat die angenommene Antwort das seltsame negative Zeichen). Ich habe mich entschieden, es nicht so zu machen, wenn sie den Fehler beheben (es ist nicht wirklich ein Fehler, wenn Sie vorhersagen, aber sie könnten es ändern) – QED

Antwort

6

mir ein Kind Klasse von CvSVM schrieb Urform zu extrahieren, nachdem eine lineare SVM trainiert. Positive Proben sind mit 1 und negative Proben mit -1 markiert. Es ist seltsam, dass ich ein negatives Vorzeichen vor Alphas setzen muss und das Zeichen von rho unverändert lassen muss, um korrekte Ergebnisse von HogDescriptor zu erhalten.

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); 
} 
+0

Sehr nette Lösung, nur eine kleine Frage @DXM: Diese Konvertierung in die ursprüngliche Form funktioniert nur für Liner SVM, was ist, wenn ich RBF-Kernel verwende? –

+1

Ich habe nicht in den Quellcode der Verwendung von RBF-Kernel in opencv geschaut. Aber ich denke, sobald Sie den Kernel auf Ihre Funktionen angewendet haben, sollte es das gleiche wie lineare SVM sein. – DXM

+0

Dies kann sehr langsam IMHO sein. Rbf-Kernel berechnen euklidische Abstände zwischen den Features und allen svm-Supportvektoren. Sehen Sie sich den Code der Vorhersage an. Ich bin neugierig auf die Art und Weise, wie Sie es in die Praxis umgesetzt haben ... – Madhatter

4

Ich hatte mit dem gleichen Problem zu kämpfen. Bei der Suche nach Foren habe ich festgestellt, dass der Detektor mit CvSVM nicht trainiert werden kann (ich kenne den Grund nicht). Ich benutzte LIBSVM zum Training des Detektors. Hier ist der Code, um den Detektor für HOGDescriptor.setSVMDetector (w) zu extrahieren: Details zu den Daten finden Sie in der LIBSVM-Dokumentation/header. Ich habe das ganze Training in C++ gemacht und die LIBSVM Trainingsdaten von CV bis LIBSVM ausgefüllt. Der folgende Code extrahiert den Detektorvektor, der für cv :: HOGDescriptor benötigt wird. Der w Parameter ist 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]); 

Hope this helps ...

+0

Haben Sie diesen Code versucht? Scheint sogar in falschen Bildern zu erkennen. – magarwal

0

Von dem, was ich in Dalal Papier über HOG Detektor gelesen, er vorschlägt, dass Fehlalarme zu entfernen, müssen wir unser Modell umschulen. Umschulung wird durchgeführt, indem ein vorläufiges Modell (dein Modell, das viele falsche positive Ergebnisse liefert) angewendet wird, dann Objekte in allen negativen Probenbildern erkannt werden. Alle zurückgegebenen Rechtecke würden definitiv falsche Positive sein.

Fügen Sie dann alle diese Fehlalarme zu Ihren negativen Beispielbildern hinzu (negativer Datensatz), führen Sie erneut ein Training durch. Das resultierende Modell wird, wie in dem Papier vorgeschlagen, viel weniger falsch positive Ergebnisse liefern.

Leider habe ich das versucht (Umschulung), aber das resultierende Modell erkennt einfach nichts, auch nicht an positiven Bildproben. Aber ich denke, es ist ein Versuch wert, denn das war das, was in dem Erfinder Papier über HOG Detektor vorgeschlagen