0

这是我用于训练例如车辆数据集的代码,当它完全训练时,我希望它从视频(.avi)中预测数据(车辆)how to predict trained data from video and how to add that part in it ?,我希望当车辆在视频中显示时它计算它为 1 并 cout 检测到物体,如果第二辆车来,则将计数增加为 2

    IplImage *img2;
    cout<<"Vector quantization..."<<endl;
    collectclasscentroids();
    vector<Mat> descriptors = bowTrainer.getDescriptors();
    int count=0;
    for(vector<Mat>::iterator iter=descriptors.begin();iter!=descriptors.end();iter++)
    {
       count += iter->rows;
    }
    cout<<"Clustering "<<count<<" features"<<endl;
    //choosing cluster's centroids as dictionary's words
    Mat dictionary = bowTrainer.cluster();
    bowDE.setVocabulary(dictionary);
    cout<<"extracting histograms in the form of BOW for each image "<<endl;
    Mat labels(0, 1, CV_32FC1);
    Mat trainingData(0, dictionarySize, CV_32FC1);
    int k = 0;
    vector<KeyPoint> keypoint1;
    Mat bowDescriptor1;
    //extracting histogram in the form of bow for each image 
   for(j = 1; j <= 4; j++)
    for(i = 1; i <= 60; i++)
            {
              sprintf( ch,"%s%d%s%d%s","train/",j," (",i,").jpg");
              const char* imageName = ch;
              img2 = cvLoadImage(imageName, 0); 
              detector.detect(img2, keypoint1);
              bowDE.compute(img2, keypoint1, bowDescriptor1);
              trainingData.push_back(bowDescriptor1);
              labels.push_back((float) j);
             }
    //Setting up SVM parameters
    CvSVMParams params;
    params.kernel_type = CvSVM::RBF;
    params.svm_type = CvSVM::C_SVC;
    params.gamma = 0.50625000000000009;
    params.C = 312.50000000000000;
    params.term_crit = cvTermCriteria(CV_TERMCRIT_ITER, 100, 0.000001);
    CvSVM svm;



    printf("%s\n", "Training SVM classifier");

    bool res = svm.train(trainingData, labels, cv::Mat(), cv::Mat(), params);

    cout<<"Processing evaluation data..."<<endl;


    Mat groundTruth(0, 1, CV_32FC1);
    Mat evalData(0, dictionarySize, CV_32FC1);
    k = 0;
    vector<KeyPoint> keypoint2;
    Mat bowDescriptor2;


    Mat results(0, 1, CV_32FC1);;
    for(j = 1; j <= 4; j++)
      for(i = 1; i <= 60; i++)
         {
           sprintf( ch, "%s%d%s%d%s", "eval/", j, " (",i,").jpg");
           const char* imageName = ch;
           img2 = cvLoadImage(imageName,0);
           detector.detect(img2, keypoint2);
           bowDE.compute(img2, keypoint2, bowDescriptor2);
           evalData.push_back(bowDescriptor2);
           groundTruth.push_back((float) j);
           float response = svm.predict(bowDescriptor2);
           results.push_back(response);
         }



    //calculate the number of unmatched classes 
    double errorRate = (double) countNonZero(groundTruth- results) / evalData.rows;

The question is这段代码不是从视频中预测的,我想知道如何从视频中预测它,意思就像我想从电影中检测车辆一样,当它从电影中找到车辆时应该显示 1

对于那些不明白这个问题的人:

我想在上面的代码中播放电影

VideoCapture cap("movie.avi"); //movie.avi is with deleted background

假设我有一个包含车辆的训练数据,并且“movie.avi”包含 5 辆车辆,所以它应该检测来自 movie.avi 的车辆并将我5作为输出

如何在上面的代码中做这部分

4

4 回答 4

2

通过查看您的代码设置

params.svm_type = CvSVM::C_SVC;

看来你用两个以上的类训练你的分类器。交通场景中的一个典型示例可能是汽车/行人/自行车/......但是,您要求一种仅检测汽车的方法。如果没有对您的训练数据和视频的描述,就很难判断您的想法是否有意义。我猜前面的答案假设如下:

您循环遍历每一帧并希望输出该帧中的汽车数量。因此,一个帧可能包含多辆汽车,比如说 5。如果您将整个帧作为分类器的输入,它可能会响应“汽车”,即使从概念上来说设置可能有点偏离。您无法使用这种方法可靠地检索汽车数量。

相反,建议尝试滑动窗口方法。这意味着,例如,您循环遍历帧的每个像素,并将像素周围的区域(称为子窗口感兴趣区域)作为分类器的输入。假设一个固定的scale,子窗口的大小可能是 150x50px 以及您的训练数据。您可能会在训练数据中固定汽车的尺寸,但在真实世界的视频中,汽车的尺寸会有所不同。为了找到不同比例的汽车,假设它是训练数据的两倍,典型的方法是缩放图像(比如用 2 倍)并重复滑动窗口方法。

通过对所有相关比例重复此操作,您最终会得到一个算法,该算法为您提供每个像素位置和每个比例的分类器结果。这意味着您有三个循环,或者换句话说,存在三个维度(图像宽度、图像高度、比例)。最好将其理解为三维金字塔。“为什么是金字塔?” 你可能会问。因为每次缩放图像(比如 2)时,图像都会变小(/变大),而下一个比例是不同大小的图像(例如一半大小)。

像素位置表示汽车的位置,比例表示汽车的大小。现在,如果你有一个 N 类分类器,这个金字塔中的每个槽都将包含一个数字 (1,...,N) 来表示该类。如果您有一个二元分类器(汽车/无汽车),那么您最终会得到每个包含 0 或 1 的插槽。即使在这种简单的情况下,您也会很想简单地计算 1 的数量并将计数输出为车的数量,您仍然会遇到同一辆车可能有多个响应的问题。因此,如果您有一个汽车检测器,它可以在 0 和 1 之间给出连续响应,然后您可以在这个金字塔中找到最大值,那就更好了。每个最大值将指示一辆车。这种检测成功地与角点特征一起使用,在所谓的角点特征中检测感兴趣的角点尺度空间金字塔

总而言之,无论您是将问题简化为二分类问题(“car”/“no car”),还是坚持区分多个类别的难度更大的任务(“car”/“animal” /"pedestrian"/...),你仍然需要解决每一帧的比例和位置问题。

于 2013-08-19T21:21:30.480 回答
0

您使用图像的代码是用 OpenCV 的 C 接口编写的,因此可能很容易坚持使用它而不是使用 C++ 视频接口。

在这种情况下,这些方面的东西应该起作用:

CvCapture *capture = cvCaptureFromFile("movie.avi");

IplImage *img = 0;
while(img = cvQueryFrame(capture))
{
       // Process image
       ...
}
于 2013-08-16T01:24:14.400 回答
0

您应该实现滑动窗口方法。在每个窗口中,您应该应用 SVM 来获取候选人。然后,一旦你完成了整个图像,你应该合并候选(如果你检测到一个对象,那么你很可能会在几个像素的移动中再次检测到它 - 这就是候选的含义) .

查看 openCV 上的 V&J 代码或 latentSVM 代码(按部分检测),看看它是如何完成的。

顺便说一句,我会使用 LatentSVM 代码(按部件检测)来检测车辆。它为汽车和公共汽车训练了模型。

祝你好运。

于 2013-08-16T10:35:52.400 回答
0

您需要检测器,而不是分类器。看看前面提到的 Haar 级联、LBP 级联、latentSVM 或 HOG 检测器。

我会解释为什么。探测器通常通过滑动窗口逐行扫描图像。在几个尺度。在每个窗口检测器中解决问题:“对象/非对象”。它可能会给您粗略的结果,但速度非常快。诸如 BOW 之类的分类器在此任务中的工作速度非常慢。然后你应该将分类器应用于检测器发现的区域。

于 2013-08-19T20:11:38.730 回答