如何改进基于HOG行人检测功能的SVM分类器?

时间:2018-01-18 11:39:39

标签: c++ opencv machine-learning svm object-detection

我在本教程的帮助下训练了一个SVM分类器:trainHOG Tutorial

它创建了一个genfiles目录,其中包含cvHOGClassifier.yamldescriptorvector.datfeatures.datsvmlightmodel.dat个文件。

我编写了以下代码来测试我的模型

#include "opencv2/imgproc.hpp"
#include "opencv2/highgui.hpp"
#include "opencv2/ml.hpp"
#include "opencv2/objdetect.hpp"

#include <fstream>
#include <iostream>
#include <time.h>

using namespace cv;
using namespace cv::ml;
using namespace std;


int main()
{
    cout << "Testing trained detector..." << endl;

    vector<float> descriptorVector;

    std::ifstream file("genfiles/descriptorvector.dat");

    float number;

    while(file >> number) 
    descriptorVector.push_back(number);

    HOGDescriptor hog;
    hog.winSize = Size(64, 128);

    hog.setSVMDetector(descriptorVector);


//  hog.load( "/home/nvidia/Desktop/HOG/genfiles/cvHOGClassifier.yaml" );

    VideoCapture cap("/home/nvidia/Desktop/test_videos/4.mp4");

    Mat img;
    Size size(1280,491);

    for(;;)
    {

    bool Is = cap.grab();

        if (Is == false) {
        cout << "Video Capture Fail" << endl;
        break;
        }

        else{

        cap.retrieve(img, CV_CAP_OPENNI_BGR_IMAGE);
        img  = imread("queue.jpg");
        resize(img,img,size);
        cvtColor(img, img, CV_BGR2GRAY);

        vector< Rect > detections;
        vector< double > foundWeights;

        Size padding(Size(8, 8));
        Size winStride(Size(8, 8));
        hog.detectMultiScale(img, detections, 0, winStride, padding);   


       vector<Rect> found_filtered;
       size_t i, j;

       for (i = 0; i < detections.size(); ++i) {
        Rect r = detections[i];
        for (j = 0; j < detections.size(); ++j)
            if (j != i && (r & detections[j]) == r)
                break;
        if (j == detections.size())
            found_filtered.push_back(r);
    }

    for (i = 0; i < found_filtered.size(); i++) {
        Rect r = found_filtered[i];
        rectangle(img, r.tl(), r.br(), Scalar(64, 255, 64), 3);
    }


        imshow( "Streaming", img );

        int key1 = waitKey(20);
            }

    }
    return 0;
}

以上代码为我提供了误报。我用15k正面64x128图像和3k负面64x128图像训练模型。在SO上阅读各种Q&amp; A对我的情况没有多大帮助。

我应该做些什么修改才能使我的模型正常工作?

1 个答案:

答案 0 :(得分:1)

可能是该模型刚刚过度装配。从我在本教程代码中看到的,他们使用svmlight并只加载数据和训练。这可能太少了。培训良好的svm模型不是那么简单(遗憾)。你可以考虑一些事情:

  1. 首先,你训练数据是不平衡的(15k正面对3k 负)。选择其中一些子集会更好 阳性样本(你甚至可以尝试选择3k阳性样本 随机地)。平衡培训数据非常重要。
  2. 要考虑的第二件事是对此进行一些交叉验证 数据集以搜索模型的良好参数。 (参见3.了解更多信息)
  3. 您使用的内核是什么?您的数据是否可以线性分离?如果不 那么你应该从RBF内核开始,看看它是否是任何 更好(记得找到带有交叉验证程序的gamma和C)
  4. 此外,当您使用opencv时,它附带了它拥有SVM。我不确定您使用的是哪个版本的OpenCv,但是这里尝试从本教程开始(opencv 3.0在svm中3.0和3.4之间应该没有变化)

    https://docs.opencv.org/3.0-beta/doc/tutorials/ml/non_linear_svms/non_linear_svms.html

    如果由于某种原因你无法使用opencv实现,那么研究如何训练好模型仍然是有益的。这是理解svm的非常好的教程(它来自libcvm的作者,其中opencv实现基于):

    https://www.csie.ntu.edu.tw/~cjlin/papers/guide/guide.pdf