【问题标题】:How to fix HOG to detect all the persons in a scene?如何修复 HOG 以检测场景中的所有人?
【发布时间】:2016-05-17 03:36:00
【问题描述】:

我想使用 HOG 描述符和 SVM 检测场景中的人,但程序没有检测到场景中的所有当前人:

#include <opencv2/opencv.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv/cv.h>
#include <iostream>
#include <vector>




using namespace std;
using namespace cv;


vector <Rect> drawBoundingBox (vector<vector<Point> > contours)
{
    vector <Rect> listOfRectangles; 
    for (int i = 0; i< contours.size(); i++)
    {
        // Get bounding box for contour
        Rect roi = boundingRect(contours[i]);
        if (roi.area() > 1000)
        {
            listOfRectangles.push_back(roi);
        }
    }
    //merge rectangles
    int size = listOfRectangles.size();
    for( int k = 0; k < size; k++ )
    {
        listOfRectangles.push_back(Rect(listOfRectangles[k]));
    }
    groupRectangles(listOfRectangles, 1, 0.7);
    return listOfRectangles; 
}


//! main program 
int main(int argc, char* argv[])
{

    Mat frame_capture,frame_capture2;  
    VideoCapture capture("Baseline/PETS2006/input/in%06d.jpg");   // path to input images
    VideoCapture capture2("Baseline/PETS2006/groundtruth/gt%06d.png"); // path to groundtruth images



    if((!capture.isOpened())&(!capture2.isOpened() )) 
    {
        printf("Could not open video file!!!");
        cin.get();
        return -1;
    }

    Mat gray;

    //! do detection and tracking
    int i=0;


    //Hog Descriptor
    cv::HOGDescriptor hog;
    hog.setSVMDetector(cv::HOGDescriptor::getDefaultPeopleDetector());

    while (1)
    {   ++i;
        capture >> frame_capture;
        capture2 >> frame_capture2;
        if(i >= 300){

        cv::cvtColor(frame_capture2,gray, CV_RGB2GRAY);


        cv::Mat im_gray;
        cv::equalizeHist( gray, im_gray );
        vector<vector<Point> > contours;
        vector<Vec4i> hierarchy;
        findContours(gray,contours, hierarchy, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_SIMPLE, Point(0, 0) );
        vector <Rect> listOfRectangles;
        listOfRectangles = drawBoundingBox(contours);


         // HOG person detector
            vector <Rect>  detected_person;


         //Hog detectMultiscale
           hog.detectMultiScale(im_gray, detected_person, 0.0, cv::Size(8, 8), cv::Size(0,0), 1.05, 4); 



    if(!frame_capture.empty()){
        for (int i =0; i<detected_person.size();++i)
        {
            //rectangle (frame_capture, listOfRectangles[i], Scalar(255,255,0),1,8,0); //! display detections


            //detected persons
            rectangle(frame_capture, detected_person[i], Scalar(255,255,0),2,8,0);
            //putText(frame_capture,"person", detected_person[i].tl(),FONT_HERSHEY_COMPLEX_SMALL,0.8,cvScalar(200,200,250),1,CV_AA);

        }


    //oVideoWriter.write(frame_capture);
        imshow("video",frame_capture);
        waitKey(25);
    }    
    }
    }
    destroyAllWindows();
    return 0;

}

我得到了这样的结果这张图片。我该怎么做才能使用这种方法检测场景中存在的所有人?有人知道如何解决这个问题吗?

【问题讨论】:

  • 在背景中添加更多光线。
  • 如果后面的人太小(最小检测器尺寸是人高约为 110 像素),您可以尝试调整图像大小(增加图像大小)
  • 我使用的是 720*576 图片。
  • 放人不填满整个图像大小。 PERSON(不是图像)的最小像素高度应该是 110 像素左右(我没有在你的图像中测量它)
  • 不需要正好是 110,也可以更大。如果将整个图像的大小调整 1.5 倍,您也会检测到第二个人(右上角)。我没有设法检测到第三个,因为我说过你应该为场景添加更多的光(可能不可能,但无论如何你不应该假设完美的结果)。欢迎来到视频检测的世界。

标签: opencv image-processing


【解决方案1】:

HOG 不是一次应用于整个图像,而是应用于从图像中提取的窗口。这些窗口默认为 64x128,重叠 8 个像素。这种检测方法依赖于假设,即人类必须大致填满整个检测窗口并适应其中。当您想检测尺寸不同于 ~64x128 的人时,您应该创建一组缩放图像,这样就更有可能将人放入其中一个窗口。

但是,在您的代码中,您使用 getDefaultPeopleDetector() 进行分类,使用 detectMultiScale(),这基本上可以为您进行缩放。可能还有其他一些问题 - 请注意,这两个人与背景融合了一点,因此 HOG 可能会错误地计算他们的边缘,并且分类器可以将他们视为非人对象。遮挡可能是另一个问题。

您应该使用其他图像测试您的代码并检查是否总是出现问题。尝试使用detectMultiScale() - scaleFactor 的不同参数,它描述了缩放的步骤,minNeighbors 描述了需要多少个被 SVM 分类为包含人的相邻窗口才能最终将对象标记为人。使用 RGB 代替灰度也应该改进分类。最后,您还可以尝试训练自己的 SVM。

但是,请记住,要获得 100% 的检测器准确度是不可能的(至少到目前为止)。看看Dalal and Triggs article 关于行人检测的 HOG 是个好主意,以了解 OpenCV 实现的幕后情况(部分基于那篇文章)。

【讨论】:

  • afaik detectMultiscale 只会缩小图像(或放大检测窗口)。这就是为什么这些人必须具有一定的最小尺寸才能被检测到。
  • 我认为根据 scaleFactor 是 >1 还是
  • @BartekM:如何调整图像中检测到的对象的大小??
  • 您调整整个图像的大小并获得不同比例的图像集(称为金字塔)。使用 opencv resize() 调整大小。不要忘记缩小后的图像不能小于检测窗口。
  • 我可能把你的问题弄错了。您的意思是:如何从调整大小的图像中的位置计算原始图像中检测到的对象(在调整大小的图像中检测到)的位置?
猜你喜欢
  • 1970-01-01
  • 2019-02-06
  • 2015-05-05
  • 2014-07-05
  • 1970-01-01
  • 2015-04-28
  • 2022-08-18
  • 2016-02-17
  • 2015-08-12
相关资源
最近更新 更多