使用openCV提高人体检测能力

5

我在openCV上尝试了一个有关人员检测的示例。在对一张图片(可在这里找到原始图片)运行后,得出了以下结果:

enter image description here

我使用的是openCV捆绑的人员检测示例(稍作修改以避免Visual Studio错误)。以下是执行的代码:

    // opencv-sample.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"

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

#include <stdio.h>
#include <string.h>
#include <ctype.h>

using namespace cv;
using namespace std;

// static void help()
// {
//     printf(
//             "\nDemonstrate the use of the HoG descriptor using\n"
//             "  HOGDescriptor::hog.setSVMDetector(HOGDescriptor::getDefaultPeopleDetector());\n"
//             "Usage:\n"
//             "./peopledetect (<image_filename> | <image_list>.txt)\n\n");
// }

int main(int argc, char** argv)
{
    Mat img;
    FILE* f = 0;
    char _filename[1024];

    if (argc == 1)
    {
        printf("Usage: peopledetect (<image_filename> | <image_list>.txt)\n");
        return 0;
    }
    img = imread(argv[1]);

    if (img.data)
    {
        strcpy_s(_filename, argv[1]);
    }
    else
    {
        fopen_s(&f, argv[1], "rt");
        if (!f)
        {
            fprintf(stderr, "ERROR: the specified file could not be loaded\n");
            return -1;
        }
    }

    HOGDescriptor hog;
    hog.setSVMDetector(HOGDescriptor::getDefaultPeopleDetector());
    namedWindow("people detector", 1);

    for (;;)
    {
        char* filename = _filename;
        if (f)
        {
            if (!fgets(filename, (int)sizeof(_filename) - 2, f))
                break;
            //while(*filename && isspace(*filename))
            //  ++filename;
            if (filename[0] == '#')
                continue;
            int l = (int)strlen(filename);
            while (l > 0 && isspace(filename[l - 1]))
                --l;
            filename[l] = '\0';
            img = imread(filename);
        }
        printf("%s:\n", filename);
        if (!img.data)
            continue;

        fflush(stdout);
        vector<Rect> found, found_filtered;
        double t = (double)getTickCount();
        // run the detector with default parameters. to get a higher hit-rate
        // (and more false alarms, respectively), decrease the hitThreshold and
        // groupThreshold (set groupThreshold to 0 to turn off the grouping completely).
        hog.detectMultiScale(img, found, 0, Size(8, 8), Size(32, 32), 1.05, 2);
        t = (double)getTickCount() - t;
        printf("tdetection time = %gms\n", t*1000. / cv::getTickFrequency());
        size_t i, j;
        for (i = 0; i < found.size(); i++)
        {
            Rect r = found[i];
            for (j = 0; j < found.size(); j++)
                if (j != i && (r & found[j]) == r)
                    break;
            if (j == found.size())
                found_filtered.push_back(r);
        }
        for (i = 0; i < found_filtered.size(); i++)
        {
            Rect r = found_filtered[i];
            // the HOG detector returns slightly larger rectangles than the real objects.
            // so we slightly shrink the rectangles to get a nicer output.
            r.x += cvRound(r.width*0.1);
            r.width = cvRound(r.width*0.8);
            r.y += cvRound(r.height*0.07);
            r.height = cvRound(r.height*0.8);
            rectangle(img, r.tl(), r.br(), cv::Scalar(0, 255, 0), 3);
        }
        imshow("people detector", img);
        imwrite("detected_ppl.jpg", img);
        int c = waitKey(0) & 255;
        if (c == 'q' || c == 'Q' || !f)
            break;
    }
    if (f)
        fclose(f);
    return 0;
}

我希望能够提高这个结果的准确率,至少要检测出这张图片中的11个人中的9个。如何改进这个结果?我需要训练一个单独的SVM吗?还是有更好的库可以使用?或者我需要使用深度学习技术?


你可以尝试使用Overfeat,注意它没有在OpenCV中实现。由NYU开发。这是一个预先训练好的深度卷积神经网络,你只需要训练神经网络的最后一层。它应该会给你更好的结果,这里是链接 http://cilvr.nyu.edu/doku.php?id=software:overfeat:start#overview - DXM
这可能会对您有所帮助:http://www.geocities.ws/talh_davidc/ - SomethingSomething
1个回答

6

图片描述在此

这是我花不多的时间使用示例代码实现的改进。

我的做法:
- 调整了detectMultiScale中的一些参数
- 调整滤波器以消除大部分重叠矩形

我的结果是9/11,其中一个是误报,两个是漏报。

虽然这很好,但这只是一张静态的图像。调整参数以针对单个样本会导致过度拟合:你仅仅是在那个样本上得到了你想要的响应,但泛化效果差。

我强烈建议在放弃openCV算法并尝试'更好'的库和'深度学习'方法之前,先彻底了解openCV算法。如果你不知道这种算法的优缺点,就无法与来自其他库的其他方法进行比较。

更新
这是我用来获得结果的代码,它是从peopledetect.cpp openCV示例代码中修改的。你需要进行一些更改,因为我使用了一个自定义图像读取函数,这对你来说不相关。

我已经添加了一个滑块来调整'scaleFactor'参数,以便你轻松查看它的效果。detectMultiscale在多个大小上运行分类器窗口,并在多个步骤中缩放图像。scaleFactor参数影响每个步骤的尺寸步骤,稍微调整该设置就会对输出产生巨大影响。但是,在单个静态图像上调整这些参数有点没有意义,你真正需要的是让它在代表性测试集上自由运行,以评估这种(或其他任何)算法的适用性。


你能否更具建设性一些呢?如果我知道如何使其工作,我就不会问这个问题了。你调整了哪些参数?默认设置下,detectMultiScale是如何实现多尺度比较以保持尺度不变的呢? - dev_nut
@dev_nut - 说得好,我已经更新了我的答案,并链接到了我用来得出那个结果的代码。我有点不耐烦是因为你似乎连调整任何参数来探索算法都没有尝试过,所以现在就寻求替代方案似乎有点过早了。 - foundry
谢谢!我相信我被detectMultiScale这个名字误导了。实际上,我添加了一个trackbar来调整图像的大小(而不是调整比例因子),但是没有成功使其工作。我使用提供的示例提出了问题,以便不会用不必要的细节困扰读者。 - dev_nut

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接