Opencv - Haar级联 - 人脸跟踪非常缓慢

10

我使用OpenCV库开发了一个通过摄像头跟踪人脸的项目。我使用带有haarcascade_frontalface_alt.xml的haar级联来检测人脸。

我的问题是,如果从网络摄像头中捕获的图像不包含人脸,则检测人脸的过程非常缓慢,因此向用户连续显示的相机图像会延迟。

我的源代码:

void camera() 
{
    String face_cascade_name = "haarcascade_frontalface_alt.xml";
    String eye_cascade_name = "haarcascade_eye_tree_eyeglasses.xml";
    CascadeClassifier face_cascade;
    CascadeClassifier eyes_cascade;
    String window_name = "Capture - Face detection";
    VideoCapture cap(0);

    if (!face_cascade.load(face_cascade_name))
        printf("--(!)Error loading\n");

    if (!eyes_cascade.load(eye_cascade_name))
        printf("--(!)Error loading\n");

    if (!cap.isOpened()) 
    {
        cerr << "Capture Device ID " << 0 << "cannot be opened." << endl;
    } 
    else 
    {
        Mat frame;
        vector<Rect> faces;
        vector<Rect> eyes;
        Mat original;
        Mat frame_gray;
        Mat face;
        Mat processedFace;

        for (;;) 
        {
            cap.read(frame);
            original = frame.clone();    
            cvtColor(original, frame_gray, CV_BGR2GRAY);
            equalizeHist(frame_gray, frame_gray);
            face_cascade.detectMultiScale(frame_gray, faces, 2, 0,
                    0 | CASCADE_SCALE_IMAGE, Size(200, 200));

            if (faces.size() > 0)
                rectangle(original, faces[0], Scalar(0, 0, 255), 2, 8, 0);

            namedWindow(window_name, CV_WINDOW_AUTOSIZE);
            imshow(window_name, original);
        }

        if (waitKey(30) == 27)
            break;
    }
}

1
“非常慢”是什么意思?您的图像解决方案是什么?face_cascade.detectMultiScale需要一些时间。如果您已经使用了release模式的OpenCV库,那么可能还有一个机会:也许OpenCV也有一个GPU级联检测器,但我不确定。 - Micka
我的图像解决方案是640 x 480。这意味着如果图像中不包含人脸,detectMultiscale函数处理检测人脸会非常缓慢 :( - Nick Viatick
2
那么只有在没有检测到人脸时它才会变慢,而如果有人脸则会很快?!? - Micka
1
这不可能是真的吧? - maxisme
4个回答

3

Haar分类器天生速度较慢,此外,算法本身不能太多地进行优化,因为OpenCV中的detectMultiScale是并行的。

关于您的代码唯一的注意事项:您真的曾经使用minSize等于Size(200,200)检测到一些面孔吗?尽管可以肯定的是,minSize越大,性能越好。

在检测任何内容之前,请尝试缩放图像:

const int scale = 3;
cv::Mat resized_frame_gray( cvRound( frame_gray.rows / scale ), cvRound( frame_gray.cols / scale ), CV_8UC1 );
cv::resize( frame_gray, resized_frame_gray, resized_frame_gray.size() );
face_cascade.detectMultiScale(resized_frame_gray, faces, 1.1, 3, 0 | CASCADE_SCALE_IMAGE, Size(20, 20));

不要忘记将minSize更改为更合理的值,并将检测到的人脸位置转换为实际比例。

对于任何图像处理算法,尤其是涉及到一些昂贵的内容(如检测),将图像大小缩小2、3、5倍都是一个很好的性能提升。

正如之前所提到的,如果调整大小无法解决问题,请尝试使用分析器获取其他瓶颈。

您还可以切换到LBP分类器,它相对较快,但精度较低。

希望这会有所帮助。


谢谢您的帮助,但当图像中没有人脸时,detectMultiScale 过程会变得非常缓慢。 - Nick Viatick
我打算尝试将这个方法付诸实践,之前我在看到这个之前就在想这个方法是否可行。我想知道这会对检测性能造成多大的损害。相比树莓派等设备,我很困惑iPhone是如何如此轻松地完成它。 - maxisme
通过增加minSize,问题得到解决并将延迟从秒改为毫秒。非常感谢您! - eric

1

我经常使用Haar级联分类器,在Intel PC/Mac (Windows/Ubuntu/OS X)的4GB RAM和2GHz CPU上,能够轻松地在640x480的图像上获得15帧/秒的人脸检测。请问你的配置情况如何?

以下是一些你可以尝试的方法:

  1. 你不必在每一帧中创建窗口 (namedWindow(window_name, CV_WINDOW_AUTOSIZE);),只需先创建它,然后更新图像即可。

  2. 你可以尝试不使用直方图均衡化来运行程序,因为这在使用网络摄像头时并不总是需要。

  3. 如Micka所建议的那样,你应该检查程序是否在Debug模式或release模式下运行。

  4. 使用性能分析工具来查看瓶颈在哪里。

  5. 如果你注释掉人脸检测和绘制矩形,你是否已经测量过帧率?


我检查了一下,如果图像中没有人脸,我发现detectMultislace进程非常缓慢 :( - Nick Viatick
waitkey(30)语句可能会使事情变得相当缓慢。请参见http://stackoverflow.com/questions/18701236/cvwaitkey-slowing-capture-process-significantly-workaround进行讨论。 - Totoro
你是说如果没有人脸,这个函数运行速度会变慢?这肯定不可能! - maxisme
1
我在900MHZ的RPI上只得到了2FPS。 - maxisme
当没有检测功能时,我只能获得12FPS,这看起来非常糟糕。 - maxisme
你的编译器选项是什么?感谢Frogatto进行了出色的编辑! - Totoro

1

也许对您有用:

有一个名为Simd Library的库,其中包含HAAR和LBP级联分类器的实现。它可以使用OpenCV中的标准HAAR和LBP级联。该实现使用SSE4.1、AVX2和NEON(ARM)进行SIMD优化,因此比原始的OpenCV实现快2-3倍。


你的库看起来很酷。它与 Agner Fog 的 Vector Class Library 或 Yeppp! 相比如何? - Z boson
据我所知,Agner Fog的向量类库和Yeppp是通用目的的向量库。Simd库更与图像处理相关。 - ErmIg

0

您可以使用LBP级联来检测人脸。它更加轻巧。您可以在OpenCV源目录中找到lbpcascade_frontalface.xml


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